2015年2月27日 星期五

OpenEmbedded User Manual - CH3, Writing Meta Data (Adding packages)


如同User manual提的,讓我們從寫package的description跟license開始,我們寫一個brook_1.0.bb開始

description

DESCRIPTION = "Brook's first application"
HOMEPAGE = "http://www.brook.com/oe/"
LICENSE = "Brook-Proprietary"
基本上這些參數都只是描述,也就是字串,至於LICENSE有公用哪些選項,請參考Recipe License Fields

define dependency

DEPENDS = "gtk+"
RDEPENDS = "cool-ttf-fonts"
DEPENDS是build時需要哪個package,RDEPENDS則是執行時需要哪個package,也就是說如果該brook_1.0被加到image,則RDEPENDS所列的也都會被加到image之中。

source location

SRC_URI = "http://127.0.0.1/brook/${P}.tar.bz2"
SRC_URI[md5sum] = "6abf52e3f874f67bc4663d0986493970"
SRC_URI[sha256sum] = "7aa5130f9648f0948ebaad270a4fe1112e4cc06895580dab85da26baa37fd4f6"
SRC_URI是指定檔案所在的位置,可以支援http、ftp、git、svn、file等,詳情可參考SRC_URI variable,SRC_URI[md5sum]與SRC_URI[sha256sum]是去驗證檔案是否正確,可以透過md5sum file_name與sha256sum file_name算出。當中的${P}=${PN}-${PV},${PN}是Package Name,${PV}是Package Version。

build system selection

在開始真正build package之前,我們必須決定這個package使用哪個build system,如果這個package需要先執行configure script然後在make,那麼通常就會選用autotools,更多關於autotools class,其他inherit之後再來討論。

到此可以真正開始build brook這個package了,bitbake brook

完整brook_1.0.bb

DESCRIPTION = "Brook's first application"
HOMEPAGE = "http://www.brook.com/oe/"
LICENSE = "Brook-Proprietary"
LIC_FILES_CHKSUM = "file://COPYING;md5=dcb2a5c2b6d6fea1a0835c08d71ad817"

SRC_URI = "http://127.0.0.1/brook/${P}.tar.bz2"
SRC_URI[md5sum] = "6abf52e3f874f67bc4663d0986493970"
SRC_URI[sha256sum] = "7aa5130f9648f0948ebaad270a4fe1112e4cc06895580dab85da26baa37fd4f6"
inherit autotools


Example of Source Code

brook-1.0/Makefile
all: brook

brook: main.o
 ${CC} $? -o $@
install:
 install -d -m 755 ${DESTDIR}/bin
 install -m 755 brook ${DESTDIR}/bin


brook-1.0/main.c
#include <stdio.h>

int main(int argc, char *argv[])
{
    printf("Hello world, Brook\n");
    return 0;
}


    參考資料:
  1. OpenEmbedded User Manual
  2. OpenEmbedded - Style Guide
  3. OpenEmbedded - Recipe License Fields


LIC_FILES_CHKSUM does not match

如果出現以下錯誤
ERROR: brook: Recipe file does not have license file information (LIC_FILES_CHKSUM)
ERROR: Licensing Error: LIC_FILES_CHKSUM does not match, please fix
可以在bb file中加入
LIC_FILES_CHKSUM = "file://COPYING;md5=dcb2a5c2b6d6fea1a0835c08d71ad817"

其中COPYING就是LICENSE檔案位置,我是指到source file解開後的COPYING檔案位置與其對應的md5sum。


2015年2月7日 星期六

nc — arbitrary TCP and UDP connections and listens


幾乎任何使用 TCP,UDP或UNIX-domain socket的動作都可以用nc來達成,常見的功能如。
  • simple TCP proxies
  • shell-script based HTTP clients and servers
  • network daemon testing
  • a SOCKS or HTTP ProxyCommand for ssh(1)
  • and much, much more


SYNOPSIS
     nc [-46bCDdhklnrStUuvZz] [-I length] [-i interval] [-O length]
        [-P proxy_username] [-p source_port]
        [-q seconds] [-s source] [-T toskeyword] [-V rtable]
        [-w timeout] [-X proxy_protocol] [-x proxy_address[:port]]
        [destination] [port]


options: -v, verbose

不加-v,發生錯誤時不會有訊息。
brook@vista:~$ nc 127.0.0.1 12345
brook@vista:~$ nc -v 127.0.0.1 12345
nc: connect to 127.0.0.1 port 12345 (tcp) failed: Connection refused
brook@vista:~$ nc -v 127.0.0.1 80
Connection to 127.0.0.1 80 port [tcp/http] succeeded!
輸入GET / HTTP/1.1
輸入HOST: 127.0.0.1
輸入[enter]
輸入[enter]

HTTP/1.1 200 OK
Date: Tue, 27 Jan 2015 08:24:17 GMT
Server: Apache/2.2.22 (Ubuntu)
Last-Modified: Mon, 23 Dec 2013 04:13:45 GMT
ETag: "1b806ff-b1-4ee2bdaa24ac8"
Accept-Ranges: bytes
Content-Length: 177
Vary: Accept-Encoding
Content-Type: text/html
X-Pad: avoid browser bug

<html><body><h1>It works!</h1>
<p>This is the default web page for this server.</p>
<p>The web server software is running but no content has been added, yet.</p>
</body></html>


options: -l, listen for an incoming connection rather than initiate a connection to a remote host

等同開socket在listen,預設是tcp。
brook@vista:~$ nc -l 127.0.0.1 5000 -> server
brook@vista:~$ netstat -nal | grep 5000
tcp        0      0 127.0.0.1:5000          0.0.0.0:*               LISTEN
brook@vista:~$ nc 127.0.0.1 5000 -> client


options: -u, Use UDP instead of the default option of TCP.

使用UDP取代預設的TCP
brook@vista:~$ nc -lu 127.0.0.1 5000 -> server
brook@vista:~$ nc -u 127.0.0.1 5000 -> client


使用nc當Web Server

{ echo -ne "HTTP/1.0 200 OK\r\nContent-Length: $(wc -c < some.file)\r\n\r\n"; cat some.file; } | nc -l 5050
開啟Browser,http://127.0.0.1:5050/,就可以看到網頁了。

Works as a Port Scanner

brook@vista:~$ nc -v -z 127.0.0.1 80-200 2>&1 | grep -v failed
Connection to 127.0.0.1 80 port [tcp/http] succeeded!
Connection to 127.0.0.1 139 port [tcp/netbios-ssn] succeeded!


Transfering Files

sender
brook@vista:~$ md5sum usb_eth.txt
2367562f85f99fe972b9d6a83ce38099  usb_eth.txt
brook@vista:~$ tar cvf - usb_eth.txt | nc 127.0.0.1 5000
usb_eth.txt

receiver
brook@vista:/tmp$ nc -l 5000 | tar xvf -
usb_eth.txt
brook@vista:/tmp$ md5sum usb_eth.txt
2367562f85f99fe972b9d6a83ce38099  usb_eth.txt


Git Proxy

以下的Script是我拿用當gitproxy用的
#!/bin/bash
# http://tech-tacolin.blogspot.tw/2013/04/git-http-proxy.html
PROXY=1.2.3.4
PROXYPORT=3128
case $1 in
    192.168.1.1 | internal-ip)
        nc -X connect $*
        ;;
    *)
        nc -x $PROXY:$PROXYPORT -X connect $*
        ;;
esac


    參考資料
  1. Netcat WIKI
  2. Netcat(Linux nc 指令)網路管理者工具實用範例



2014年10月19日 星期日

od - dump files in octal and other formats


od(octal dump)主要是用來將資料轉成可讀的格式(human-readable formats),預設顯示格式如同名稱,顯示8進位資料,顯示格式包含8/10/16進位,以及ASCII顯示格式。
brook@vista:~$ echo abc| od
0000000 061141 005143
0000004
brook@vista:~$ echo abc| od -o
0000000 061141 005143
0000004
brook@vista:~$ echo abc| od -d
0000000 25185  2659
0000004
jpr@jpr-Veriton-M4610:~$ echo abc| od -h
0000000 6261 0a63
0000004
brook@vista:~$ echo abc| od -c
0000000   a   b   c  \n
0000004
brook@vista:~$ echo abc| od -b
0000000 141 142 143 012
0000004
brook@vista:~$ echo abc| od -i
0000000   174285409
0000004
jpr@jpr-Veriton-M4610:~$ echo abc| od -l
0000000            174285409
0000004
brook@vista:~$ echo abc| od -s
0000000  25185   2659
0000004
brook@vista:~$ echo abc| od -x
0000000 6261 0a63
0000004

"a"的ascii值為,8/10/16進位值為97/61/141,所以有看到沒有參數和"-o"顯示一樣的內容,061141的10/16進位值為25185/H6261,看得出是一次顯示兩個byte,-b則是顯示一個byte,-h/-x一次顯示兩個byte的16進位,-d和-s一樣一次顯示兩個byte的10進位。
再來下面的例子是顯示address/offset的格式"-A",可以搭配"oxnd",o是8進位,d是10進位,d是16進位,n是不顯示address/offset。
brook@vista:~$ od -Ad sleep.sh
0000000  1647255843  1932488297  1752631912   543517801
0000016  1920213083  1562404213  1868827195  1819478282
0000032   544236901  1695091249   544172131  1701606183
0000048   824209509   660825459  1852793866   168442725
0000064
brook@vista:~$ od -Ao sleep.sh
0000000  1647255843  1932488297  1752631912   543517801
0000020  1920213083  1562404213  1868827195  1819478282
0000040   544236901  1695091249   544172131  1701606183
0000060   824209509   660825459  1852793866   168442725
0000100
brook@vista:~$ od -Ax sleep.sh
000000  1647255843  1932488297  1752631912   543517801
000010  1920213083  1562404213  1868827195  1819478282
000020   544236901  1695091249   544172131  1701606183
000030   824209509   660825459  1852793866   168442725
000040
brook@vista:~$ od -An sleep.sh
  1647255843  1932488297  1752631912   543517801
  1920213083  1562404213  1868827195  1819478282
   544236901  1695091249   544172131  1701606183
   824209509   660825459  1852793866   168442725

其餘參數包含"-N"讀幾個byte,與"-j"offset幾個byte,"-t"輸出格式顯示方式,"-t"可以搭配dfoux,後面再搭配數字,以一次幾個byte顯示。如
brook@vista:~$ od -An -N6 -t x1 sleep.sh
 23 21 2f 62 69 6e
brook@vista:~$ od -An -N6 -t x2 sleep.sh
 2123 622f 6e69
brook@vista:~$ od -An -N6 -t x4 sleep.sh
 622f2123 00006e69


我常拿od來產生random MAC,
brook@vista:~$ od -An -N6 -t x1 sleep.sh | tr ' ' ':' | cut -d':' -f2-7
23:21:2f:62:69:6e




2014年7月6日 星期日

[轉載]Linux中tty、pty、pts的概念區別


轉自 http://www.wretch.cc/blog/redsonoma/14021073

基本概念:

1> tty(終端設備的統稱):
tty一詞源於Teletypes,或者teletypewriters,原來指的是電傳打字機,是通過串行線用打印機鍵盤通過閱讀和發送信息的東西,後來這東西被鍵盤與顯示器取代,所以現在叫終端比較合適。
終端是一種字符型設備,它有多種類型,通常使用tty來簡稱各種類型的終端設備。


2> pty(虛擬終端):
但是如果我們遠程telnet到主機或使用xterm時不也需要一個終端交互麼?是的,這就是虛擬終端pty(pseudo-tty)


3> pts/ptmx(pts/ptmx結合使用,進而實現pty):
pts(pseudo-terminal slave)是pty的實現方法,與ptmx(pseudo-terminal master)配合使用實現pty。

Linux終端:

在Linux系統的設備特殊文件目錄/dev/下,終端特殊設備文件一般有以下幾種:
1、串行端口終端(/dev/ttySn)
串行端口終端(Serial Port Terminal)是使用計算機串行端口連接的終端設備。計算機把每個串行端口都看作是一個字符設備。有段時間這些串行端口設備通常被稱為終端設備,因為 那時它的最大用途就是用來連接終端。這些串行端口所對應的設備名稱是/dev/tts/0(或/dev/ttyS0), /dev/tts/1(或/dev/ttyS1)等,設備號分別是(4,0), (4,1)等,分別對應於DOS系統下的COM1、COM2等。若要向一個端口發送資料,可以在命令行上把標準輸出重定向到這些特殊文件名上即可。例如, 在命令行提示符下鍵入:echo test > /dev/ttyS1會把單詞」test」發送到連接在ttyS1(COM2)端口的設備上。可接串口來實驗。

2、偽終端(/dev/pty/)
偽終端(Pseudo Terminal)是成對的邏輯終端設備(即master和slave設備, 對master的操作會反映到slave上)。
例如/dev/ptyp3和/dev/ttyp3(或者在設備文件系統中分別是/dev/pty/m3和 /dev/pty/s3)。它們與實際物理設備並不直接相關。如果一個程序把ptyp3(master設備)看作是一個串行端口設備,則它對該端口的讀/ 寫操作會反映在該邏輯終端設備對應的另一個ttyp3(slave設備)上面。而ttyp3則是另一個程序用於讀寫操作的邏輯設備。

這樣,兩個程序就可以通過這種邏輯設備進行互相交流,而其中一個使用ttyp3的程序則認為自己正在與一個串行端口進行通信。這很像是邏輯設備對之間的管 道操作。對於ttyp3(s3),任何設計成使用一個串行端口設備的程序都可以使用該邏輯設備。但對於使用ptyp3的程序,則需要專門設計來使用 ptyp3(m3)邏輯設備。

例如,如果某人在網上使用telnet程序連接到你的計算機上,則telnet程序就可能會開始連接到設備 ptyp2(m2)上(一個偽終端端口上)。此時一個getty程序就應該運行在對應的ttyp2(s2)端口上。當telnet從遠端獲取了一個字符 時,該字符就會通過m2、s2傳遞給 getty程序,而getty程序就會通過s2、m2和telnet程序往網絡上返回」login:」字符串信息。這樣,登錄程序與telnet程序就通 過「偽終端」進行通信。通過使用適當的軟件,就可以把兩個甚至多個偽終端設備連接到同一個物理串行端口上。

在使用設備文件系統 (device filesystem)之前,為了得到大量的偽終端設備特殊文件,使用了比較複雜的文件名命名方式。因為只存在16個ttyp(ttyp0—ttypf) 的設備文件,為了得到更多的邏輯設備對,就使用了象q、r、s等字符來代替p。例如,ttys8和ptys8就是一個偽終端設備對。不過這種命名方式目前 仍然在RedHat等Linux系統中使用著。

但Linux系統上的Unix98並不使用上述方法,而使用了」pty master」方式,例如/dev/ptm3。它的對應端則會被自動地創建成/dev/pts/3。這樣就可以在需要時提供一個pty偽終端。目錄 /dev/pts是一個類型為devpts的文件系統,並且可以在被加載文件系統列表中看到。雖然「文件」/dev/pts/3看上去是設備文件系統中的 一項,但其實它完全是一種不同的文件系統。
即: TELNET ---> TTYP3(S3: slave) ---> PTYP3(M3: master) ---> GETTY
=========================================================================
實驗:
1、在X下打開一個或N個終端窗口
2、#ls /dev/pt*
3、關閉這個X下的終端窗口,再次運行;比較兩次輸出信息就明白了。
在RHEL4環境下: 輸出為/dev/ptmx /dev/pts/1存在一(master)對多(slave)的情況
=========================================================================


3、控制終端(/dev/tty)
如果當前程序有控制終端(Controlling Terminal)的話,那麼/dev/tty就是當前程序的控制終端的設備特殊文件。可以使用命令」ps –ax」來查看程序與哪個控制終端相連。對於你登錄的shell,/dev/tty就是你使用的終端,設備號是(5,0)。使用命令」tty」可以查看它 具體對應哪個實際終端設備。/dev/tty有些類似於到實際所使用終端設備的一個聯接。


4、控制台終端(/dev/ttyn, /dev/console)
在Linux 系統中,計算機顯示器通常被稱為控制台終端 (Console)。它仿真了類型為Linux的一種終端(TERM=Linux),並且有一些設備特殊文件與之相關聯:tty0、tty1、tty2 等。當你在控制台上登錄時,使用的是tty1。使用Alt+[F1—F6]組合鍵時,我們就可以切換到tty2、tty3等上面去。tty1–tty6等 稱為虛擬終端,而tty0則是當前所使用虛擬終端的一個別名,系統所產生的信息會發送到該終端上(這時也叫控制台終端)。因此不管當前正在使用哪個虛擬終 端,系統信息都會發送到控制台終端上。你可以登錄到不同的虛擬終端上去,因而可以讓系統同時有幾個不同的會話期存在。只有系統或超級用戶root可以向 /dev/tty0進行寫操作 即下例:
1、# tty(查看當前TTY)
/dev/tty1
2、#echo "test tty0" > /dev/tty0
test tty0


5 虛擬終端(/dev/pts/n)
在Xwindows模式下的偽終端.


6 其它類型
Linux系統中還針對很多不同的字符設備存在有很多其它種類的終端設備特殊文件。例如針對ISDN設備的/dev/ttyIn終端設備等。這裡不再贅述。


FAQ: 終端和控制台

Q:/dev/console 是什麼?

A:/dev/console即控制台,是與操作系統交互的設備,系統將一些信息直接輸出到控制台上。目前只有在單用戶模式下,才允許用戶登錄控制台。


Q:/dev/tty是什麼?

A:tty設備包括虛擬控制台,串口以及偽終端設備。
/dev/tty代表當前tty設備,在當前的終端中輸入 echo 「hello」 > /dev/tty ,都會直接顯示在當前的終端中。


Q:/dev/ttyS*是什麼?

A:/dev/ttyS*是串行終端設備。


Q:/dev/pty*是什麼?

A:/dev/pty*即偽終端,所謂偽終端是邏輯上的終端設備,多用於模擬終端程序。例如,我們在X Window下打開的終端,以及我們在Windows使用telnet 或ssh等方式登錄Linux主機,此時均在使用pty設備(準確的說在使用pty從設備)。

Q:/dev/tty0與/dev/tty1 …/dev/tty63是什麼?它們之間有什麼區別?

A:/dev/tty0代表當前虛擬控制台,而/dev/tty1等代表第一個虛擬控制台,例如當使用ALT+F2進行切換時,系統的虛擬控制台為/dev/tty2 ,當前的控制台則指向/dev/tty2

Q:如何確定當前所在的終端(或控制台)?

A:使用tty命令可以確定當前的終端或者控制台。

Q:/dev/console是到/dev/tty0的符號鏈接嗎?

A: 目前的大多數文本中都稱/dev/console是到/dev/tty0的鏈接(包括《Linux內核原始碼情景分析》),但是這樣說是不確切的。根據內 核文檔,在2.1.71之前,/dev/console根據不同系統的設定可以鏈接到/dev/tty0或者其他tty*上,在2.1.71版本之後則完 全由內核控制。目前,只有在單用戶模式下可以登錄/dev/console(可以在單用戶模式下輸入tty命令進行確認)。

Q:/dev/tty0與/dev/fb*有什麼區別?

A: 在Framebuffer設備沒有啟用的系統中,可以使用/dev/tty0訪問顯卡。

Q:關於終端和控制台的區別可以參考哪些文本

A: 可以參考內核文檔中的 Documents/devices.txt 中關於」TERMINAL DEVICES」的章節。另外,《Linux內核原始碼情景分析》的8.7節 以及《Operating Systems : Design and Implementation》中的3.9節(第3版中為3.8節)都對終端設備的概念和歷史做了很好的介紹。另外在《Modern Operating system》中也有對終端設備的介紹,由於與《Operating Systems : Design and Implementation》的作者相同,所以文本內容也大致相同。需要注意的一點是《Operating Systems : Design and Implementation》中將終端設備分為3類,而《Modern Operating system》將終端硬體設備分為2類,差別在於前者將 X Terminal作為一個類別。

PS:

只有2410的2.6才叫ttySAC0,9200等的還是叫ttyS0





vim - statusline


status line會在vim底下有一個視窗,用以顯示狀態,透過laststatus=0關閉status line,或laststatus=2永遠開啟status line。透過statusline設定要顯示那些東西,以及如何顯示,基本上就是"%"加上修飾字(vim的document稱為item),如%F會顯示含路徑檔案名稱,%f顯示不含路徑檔案名稱,其他一般文字會被直接顯示,如set statusline=%l/%L,就會顯示"目前所在行數/全部行數",如8/50之類的字眼。而空白要用"\"escape。

有幾個特別的修飾字(item),如"*"是設定highlight group,根據group number設定前景與背景顏色,如
set statusline=%2*%F
hi User2 ctermfg=3  ctermbg=0
會將%F(顯示含路徑檔案名稱)顯示前景為黃色的字體。


修飾字(item)"<"則會截去過長的字串。修飾字(item)"="會把status分成左右兩部分,即靠左靠右對齊。其餘的翻翻document吧。


以下是我常用的vim設定,

set statusline=
set statusline+=%1*\[%n]                                  "buffernr
set statusline+=%2*\ %<%F\                                "File+path
set statusline+=%3*\ %=\ %{''.(&fenc!=''?&fenc:&enc).''}\ "Encoding
set statusline+=%4*\ %{(&bomb?\",BOM\":\"\")}\            "Encoding2
set statusline+=%5*\ %{&ff}\                              "FileFormat (dos/unix..)
set statusline+=%6*\ row:%l/%L\ col:%03c\ (%03p%%)\             "Rownumber/total (%)
set statusline+=%0*\ \ %m%r%w\ %P\ \                      "Modified? Readonly? Top/bot.
hi User2 ctermfg=3  ctermbg=0
hi User6 ctermfg=3  ctermbg=4
set laststatus=2




參考資料
  1. vim document - statusline, http://vimdoc.sourceforge.net/htmldoc/options.html#'statusline'
  2. vim document - status-line, http://vimdoc.sourceforge.net/htmldoc/windows.html#status-line
  3. Learn Vimscript the Hard Way, Status Lines





2014年6月15日 星期日

git - push to non-bare repository


如果push到non-bare的repository,則會被reject,必須將該repository的receive.denyCurrentBranch設為ignore

brook@vista:~/x2$ git push origin HEAD
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 227 bytes, done.
Total 2 (delta 0), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can set 'receive.denyCurrentBranch' configuration variable t
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing int
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, see
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To /home/brook/x
 ! [remote rejected] HEAD -> master (branch is currently checked out)
error: failed to push some refs to '/home/brook/x'

編輯該repoistory底下的.git/config
[receive]
    denyCurrentBranch = ignore


相關文章:
git筆記





2013年9月28日 星期六

RFC 5969 - IPv6 Rapid Deployment on IPv4 Infrastructures (6rd) -- Protocol Specification之筆記


Abstract

描述6rd prefix + IPv4 address的方式定址的優點,如automatic IPv6 prefix delegation to site, statless operation, simple provisioning and service等等。


Introduction

6rd機制成功的被商業化,被詳細記錄在RFC 5569。6rd是基於6to4改善而來,主要差異是在IPv6 Prefix的部分,6to4是用2002::/16,6rd是SP(service provider)自訂的prefix。6to4也可以被視為是6rd的subset,因為如果6rd的prefix是2002::/16就是6to4了。


Terminology

6rd prefix 被SP用來給6rd domain的IPv6 prefix。SP可以布署一個以上的6rd domain。
6rd CE (Customer Edge) 在6rd的布置中擔任CPE(Customer Premises Equipment)的角色或稱RG (Residential Gateway)。典型的CE有一個WAN site interface和一個以上的LAN interface,LAN端也稱為Customer-facing。提供IP6能力,WAN端也稱SP-facing。
6rd delegated prefix 由CE計算給Customer site端使用的IPv6 Prefix。
6rd domain 使用相同的virtual 6rd link的CEs和BRs的集合。SP可以有一個以上的6rd doamin。每個6rd domain必須使用不同的6rd prefix。
6rd Border Relay 被佈署在6rd domain的edge位置。IPv4-enabled interface用於6rd的IPv6 in IPv4 tunnel端。IPv6 interface用於連接IPv6網路。
BR IPv4 address 6rd Border Relay的IPv4 address。
6rd virtual interface encapsulation and decapsulation of IPv6 packets inside IPv4。


6rd Prefix Delegation

6rd delegated prefix是利用6rd prefix和CE的IPv4計算出來,用於customer site。如圖一:
當IPv4 address在6rd domain可以被aggregate,如10.0.0.0/8,則不使用全部的IPv4來計算,因為前面8bit可以被aggregate,所以使用後面24bit(即o bit為24)。
6rd不限於使用public IP,但如果private address會overlap,就應該被切成不同的6rd domain(使用不同的6rd prefix, 可以確保唯一性)。
即使相同的SP,也可能使用不同的IPv4 bit數,比如10.0.0.0/8和192.168.0.1/16之間的差異就可能會使用不同的IPv4MaskLen。
6rd delegated prefix是使用IPv4計算,所以IPv4 address的變動,也會影響6rd delegated prefix,因此建議以IPv4 address的lease time當成prefix的lifetime。


6rd Configuration

6rd有四個重要的configured value:
IPv4MaskLen ignore最高的幾個bit,比如IPv4 address range是10.0.0./8,那麼IPv4MaskLen就是8,使用後面24bit來計算6rd delegated prefix。
6rdPrefix 6rd IPv6 prefix
6rdPrefixLen 6rd IPv6 prefix length.
6rdBRIPv4Address 6rd Border Relay的IPv4 address.


Customer Edge Configuration
這四個configured value可透過TR-69,PPP或手動方式設定,這份RFC使用DHCP方式取得參數。

6rd DHCPv4 Option

6rdBRIPv4Address允許一個以上,不過OPTION_6RD只能限制最多只有一個6rd domain,不支援多個6rd domain。當6rd被啟動, CE會設定default route到BR,比如CE IP: 10.100.100.1/8, BR IP: 10.0.0.1, 6rdPrefix: 201:db8/32,那麼CE的routing table會是這樣:
     ::/0 -> 6rd-virtual-int0 via 2001:db8:0:100:: (default route)
     2001:db8::/32 -> 6rd-virtual-int0 (direct connect to 6rd)
     2001:db8:6464:100::/56 -> Null0 (delegated prefix null route)
     2001:db8:6464:100::/64 -> Ethernet0 (LAN interface)

Border Relay Configuration
BR的位址可以利用anycast address達到loading baalancing和reliability.


IPv6 in IPv4 Encapsulation

IPv6的Traffic class field必須被複製到IPv4的Tos欄位(可以參考RFC 4213/3056/2983/3168等)。

Maximum Transmission Unit
6rd的MTU應該被設成CE WAN side的MTU - 20 bytes(IPv4 header),如果IPv4 MTU是1500,那麼6rd Tunnel MTU應該被設成1500-20=1480。如果缺乏資訊,6rd MTU應該被設成1280。

Receiving Rules
為了防止spoofing攻擊,6rd的BR和CE應該根據6rd domain的參數,驗證6rd Tunnel的IPv4 address和IPv6 address的IPv4部分是否相符,不符合就drop。


IPv6 Address Space Usage

基本上就是6rd prefix length和IPv4MaskLen的取捨,如果要給user的6rd delegated prefix是 /60,而IPv4MaskLen是24(根據IPv4 aggregate的程度),那麼6rdPrefixLen就要給60-24=36。



    參考資料:
  1. RFC 5969 - IPv6 Rapid Deployment on IPv4 Infrastructures (6rd) -- Protocol Specification




2013年9月21日 星期六

RFC 5569 - IPv6 Rapid Deployment on IPv4 Infrastructures (6rd)之筆記


Abstract

6rd是建立在6to4的機制上,提供ISP快速布建IPv6網路的機制,
和6to4相似處:
  statless IPv6(IPv6 prefix + IPv4 address information),並且將IPv6封裝在IPv4上在IPv4-only網路上傳送。
和6to4不同處:
  6to4使用2002::/16的prefix,而6rd使用ISP給的prefix。


Introduction

描述Free這間ISP成功的使用6rd快速布建IPv6網路(5周),而且低成本,變動少。


Problem Statement and Purpose of 6rd

ISP/Customer/Application之間的死結,影響IPv6布置的速度。
ISP等待Customer有需求才會想布置IPv6,而客戶只有當應程式需要IPv6才會想用IPv6,應用程式卻因為沒有IPv6所以在NAT底下繼續奮鬥。
ISPs wait for customer demand before deploying IPv6; customers don't demand IPv6 as long as application vendors announce that their products work on existing infrastructures (that are IPv4 with NATs); application vendors focus their investments on NAT traversal compatibility as long as ISPs don't deploy IPv6.

Problem
6to4的routing問題,6to4的IPv6 address是由IPv4算出來的,如:ISP給你10.1.1.1,你的6to4 address就是2001:0a01:0101::,另外一個ISP也給他的client相同的IPv4 Addresss,而他也使用了6to4,routing就出問題了。這個問題的癥結點就是相同的prefix,如果由ISP各自給合法的Prefix,就沒這問題了。因為即使是NAT,各自的Prefix還是會不同,IPv6 address仍可保證唯一。


Specification

6rd relay server的IPv4 anycast address可以由ISP自行決定,通常會避免掉192.88.99.1這個6to4專用address。

圖中說明,6rd CPE會負責將IPv6的packet封裝在IPv4裡面,並且往6rd relay server傳送,之後就可以送到IPv6的Network去,反過來,目的地是ISP的IPv6 prefix就會經由6RD relay server送到6rd CPE去。

    參考資料:
  1. 6to4 and 6rd
  2. RFC 5569 - IPv6 Rapid Deployment on IPv4 Infrastructures (6rd)





2013年9月14日 星期六

融券現償


102/09/04券賣國泰金$42.35,保證金38,200。
102/09/12現償國泰金$43.25,應退$42.35,因為已經賣在42.35。
102/09/13收到$38200 + $42350 - 費用(60+127+33) + 利息(3) = 80333。

年/月/日 股票別 股數 單價 價金 手續費 交易稅 淨付額 擔保品 融資金額 融券保證金 借券費
102/09/04
券賣
2882
國泰金
1,000 42.35 42,350 60 127 38,200 0 42,130 38,200 33

金額詳細算法:
保證金:成交價金x 保證金成數(90%)
42350 x 0.9 = 38115

借卷費:又稱融券手續費,成交價金x融券手續費率(0.08%)
42350 x 0.0008 = 33.88

賣出手續費:成交價金 x 賣出手續費率(0.1425% X 折扣)
42350 x 0.001425 = 60.35

證交稅:成交價金x證交稅率(0.3%)
42350 x 0.003 = 127.05

融卷放空可向券商收取利息,
利息=(擔保品價金+保證金) x 融卷利率(0.2%) x 融資券計息天數/365
(38200 + 42350) x 0.002 x 8 / 365 = 3.531


    參考資料:
  1. 券商優惠列表(含融資劵利率)




2013年9月7日 星期六

DHCPv6-PD


DHCPv6 Prefix Delegation (DHCPv6-PD)定義在RFC 3633,是DHCPv6的extension (option)。主要是用來和DHCPv6-PD server要求prefix給DHCPv6-PD client其他的interface。

Network layout如下:


Server端是Windows,使用dibber,設定檔如下(server.conf):
# Logging level range: 1(Emergency)-8(Debug)
log-level 8

# Don't log full date
log-mode short

iface "區域連線 35"
{

# clients should renew every half an hour
 T1 1800

# In case of troubles, after 45 minutes, ask any server
 T2 2700

# Addresses should be prefered for an hour
 prefered-lifetime 3600

# and should be valid for 2 hours
 valid-lifetime 7200
 
 class {
   pool 5000:1234::/48
 }

 # the following lines instruct server to grant each client
 # 1 or 2 prefixes (if you have uncommented second line with pd-pool or not). 
 # For example, client might get
 # 2222:2222:2222:222:2222:993f:6485:0/112 and 
 # 1111:1111:1111:1111:1111::993f:6485:0/112
 pd-class {
        pd-pool 2222:2222:1234::/48
        pd-length 48
        T1 11111
        T2 22222
    }
 
}


pd-pool 2222:2222:1234::/48
DHCPv6-PD server管理的prefix為2222:2222:1234::/48

pd-length 48
切割單位為48,等於全部發送出去。如果pd-length 56,則會切分2^(56-48) = 256個單位分發。也就是client會收到Prefix length = 56,Prefix Address = 2222:2222:1234:xx00::的訊息。


Client端是Linux,使用wide-dhcpv6,設定檔如下(/tmp/dhcp6c.conf):
interface br0 {
   send ia-pd 1;
};

id-assoc pd 1 {
    prefix-interface usb0 {
        sla-id 2;
    };
    prefix-interface usb1 {
        sla-id 3;
    };
};


send ia-pd 1:
送出id為1的pd請求

sla-len:
這裡省略了sla-len,sla-len的設定原則如下:
64 - (The length of the delegation you are getting)
如Server的pd-length為48,那麼這邊的sla-len就要設16,不過可以省略不設。

sla-id 0:
設定prefix id,範圍為0 ~ 2^sla-len,如 sla-len = 8,那麼範圍就是0~255。


執行結果
root@lte-iad:/ramdisk/tmp# ifconfig usb0
usb0      Link encap:Ethernet  HWaddr 11:22:33:E0:E3:B9
          inet6 addr: fe80::1122:33ff:fee0:e3b9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:20 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX byt.s:RX1920 (1.8 KiB)

root@lte-iad:/ramdisk/tmp# ifconfig usb1
usb1      Link encap:Ethernet  HWaddr 11:22:33:07:16:C7
          inet6 addr: fe80::1122:33ff:fe07:16c7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:1700 (1.6 KiB)

root@lte-iad:/ramdisk/tmp# ifconfig br0
br0       Link encap:Ethernet  HWaddr 11:22:33:97:F0:E6
          inet6 addr: fe80::1122:33ff:fe97:f0e6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:630 errors:0 dropped:0 overruns:0 frame:0
          TX packets:14577 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:75873 (74.0 KiB)  TX bytes:10922a79 (1.0 MiB)

root@lte-iad:/ramdisk/tmp# dhcp6c -c /tmp/dhcp6c.conf br0
Line: 418 *** family: 10, socktype: 1, protocol: 17, flags: 1, (sockaddr) address: ::, address len: 28 ***
Line: 502 *** family: 10, socktype: 1, protocol: 17, flags: 0, (sockaddr) addres,s: ff02::1:2, address len: 28 ***

root@lte-iad:/ramdisk/tmp# ifconfig usb0
usb0      Link encap:Ethernet  HWaddr 11:22:33:E0:E3:B9
          inet6 addr: 2222:2222:1234:2:1122:33ff:fee0:e3b9/64 Scope:Global
          inet6 addr: fe80::1122:33ff:fee0:e3b9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:51 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:5090 (4.9 KiB)

root@lte-iad:/ramdisk/tmp# ifconfig usb1
usb1      Link encap:Ethernet  HWaddr 11:22:33:07:16:C7
          inet6 addr: 2222:2222:1234:3:1122:33ff:fe07:16c7/64 Scope:Global
          inet6 addr: fe80::1122:33ff:fe07:16c7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:4928 (4.8 KiB)

root@lte-iad:/ramdisk/tmp# ifconfig br0
br0       Link encap:Ethernet  HWaddr 11:22:33:97:F0:E6
          inet6 addr: fe80::1122:33ff:fe97:f0e6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1086 errors:0 dropped:0 overruns:0 frame:0
          TX packets:30600 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:134671 (131.5 KiB)  TX bytes:2324630 (2.2 MiB)







2013年8月4日 星期日

RFC 4862 - IPv6 Stateless Address Autoconfiguration之筆記


1. Introduction


這份文件主要是在規範如何自動組態(autoconfigure)host的interface的IPv6 address,以及DAD(Duplicate Address Detection)驗證address的唯一性程序。
自動組態(autoconfigure)一詞有時候也稱為無狀態自動組態(stateless autoconfigure),也僅用於host,router則不在此RFC範圍內,而之所以稱為stateless autoconfigure是因為相較於statefull DHCPv6而言,網路上並沒有像DHCP server一樣的機器記錄address使用情況,所以稱為stateless。
"autoconfigure" = "prefix" + "interface ID",router會發出RA(Router Advertisement),RA通常會攜帶Prefix information,Host收到就會根據此Prefix information再加上"interface ID"組出IPv6 address。


IPv6 address有幾個狀態,當開始autoconfigure到DAD完成前,address是不能被指定到interface的,此時稱為tentative,當唯一性確認,並指定到interface開始到Preferred Lifetime結束前稱為"preferred",之後到Valid Lifetime結束前稱為"Deprecated",Valid Lifetime結束後就稱為Invalid。
如圖:



2. Terminology


tentative address、preferred address、deprecated address、invalid address分別被標是在上圖(IPv6 Address status)綠色線(time)以上的部分。preferred lifetime、valid lifetime則是分別被標示在綠色線(time)以下的部分。



3. Design Goals

  1. 不需要手動設定address
  2. 在Small sites底下沒有DHCPv6或router也能透過Link-local address進行通訊。
  3. 在large sites底下沒有DHCPv6也能透過Router的RA進行address的configuration。
  4. 有renumbering的能力,透過lifetimes達成此目標。



4. Protocol Overview


Autoconfiguration只有在multicast-capable的link上執行,而且當該interface被enable就開始執行link-local的部分,這樣就能符合設計目標之一"在Small sites底下沒有DHCPv6或router也能透過Link-local address進行通訊"。
Autoconfiguration的處理程序
  1. tentative link-local address自動產生,此時為tentative狀態。
  2. 執行DAD(Duplicate Address Detection),送出NS(Neighbor Solicitation)。
  3. DAD成功(隔一段時間沒有收到Neighbor Advertisement),將該address指定給該interface,相關的solicited-node multicast link-layer address也會被註冊到interface中。
    DAD失敗,需要手動設定IPv6 Address。



5. Protocol Specification


5.5.3 Router Advertisement Processing
  • 如果Autonomous flag沒被設定,忽略該Prefix Information。
  • 如果Prefix是Link-Local prefix,忽略該Prefix Information。
  • 如果Preferred lifetime大於Valid lifetime,忽略該Prefix Information。



Note
RFC 2464 - Transmission of IPv6 Packets over Ethernet Networks
    4. Stateless Autoconfiguration
        An IPv6 address prefix used for stateless autoconfiguration 
        of an Ethernet interface must have a length of 64 bits.



在XP上顯示IPv6 Address


在XP中可以使用指令"ipv6"操作IPv6相關設定,也可以使用netsh指令來操作。
以下圖是顯示IPv6的information:

其中第二條紅線, 是因為privacy為enable,XP自動產生位置。
第三條紅線, 則是根據網卡資訊,自動產生,後面的時間為 valid time / preferred time,因為preffered還大於0,所以這個Address處於preffered狀態(顯示於最前面的preferred)。
第四行紅線,則是會根據指定的IPv6 address,會註冊相對應的Solicited-node multicast address。


    參考資料:
  1. RFC 4862
  2. IPv6 Address Autoconfiguration
  3. RFC 2462 IPv6 Stateless Address Autoconfiguration




2013年7月28日 星期日

ubuntu 13.04英文版裝中文輸入(注音)


apt-get install scim-chewing scim-modules-table
System Settings > Language Support > Install / Remove Languages… 選Chinese

System Settings > Language Support > keyboard input method system 選SCIM

接著啟動SCIM刪除不必要的輸入法


增加切換下一個輸入法的組合鍵




2013年6月8日 星期六

RFC 5952 - A Recommendation for IPv6 Address Text Representation 之筆記


1. Introduction

RFC 5952主要在定義IPv6 address的表示法的標準化,主要原因是因為RFC 4291 - IP Version 6 Addressing Architecture定義了IPv6 address,且提供了一些彈性表示法,卻也因為彈性導致相同的address卻有不同的表示法(換言之,不同的表示法卻是指向同一address),這會導致一些問題產生。

以下的IPv6 address都是相同的:
2001:db8:0:0:1:0:0:1
2001:0db8:0:0:1:0:0:1 
2001:db8::1:0:0:1
2001:db8::0:1:0:0:1 
2001:0db8::1:0:0:1
2001:db8:0:0:1::1 
2001:db8:0000:0:1::1
2001:DB8:0:0:1::1 



2. Text Representation Flexibility of RFC 4291


2.1. Leading Zeros in a 16-Bit Field
'It is not necessary to write the leading zeros in an individual field.'
以0為開頭的字沒必要寫,因為這樣,所以0開頭的字母可寫可不寫,如:
2001:db8:aaaa:bbbb:cccc:dddd:eeee:0001
2001:db8:aaaa:bbbb:cccc:dddd:eeee:001
2001:db8:aaaa:bbbb:cccc:dddd:eeee:01
2001:db8:aaaa:bbbb:cccc:dddd:eeee:1


2.2. Zero Compression
'A special syntax is available to compress the zeros. The use of "::" indicates one or more groups of 16 bits of zeros.'
'The "::" can only appear once in an address.'
可以將1個或多個的"0000"用::這個特殊寫法表示,不過只能出現一次如:
2001:db8:0:0:0::1
2001:db8:0:0::1
2001:db8:0::1
2001:db8::1


2.3. Uppercase or Lowercase
RFC 4291並沒有特別指明說要用大寫或小寫表示之。


3. Problems Encountered with the Flexible Model


簡單來說,就是比對會有問題,比如對eth0指定IPv6網址2001:db8:0:0:1::1,之後用ifconfig eth0| grep 來找卻找不到,因為ifconfig顯示的是2001:db8::1:0:0:1這個IPv6 address。大小寫的差異在UNIX系統更是常見,比如2001:db8:0:0:1:0:0:1和2001:DB8:0:0:1:0:0:1在比對沒有特別指明case insensitive參數就會視為不同。


4. A Recommendation for IPv6 Text Representation


4.1. Handling Leading Zeros in a 16-Bit Field
Leading zeros MUST be suppressed.0開頭的字母都必須被省略,如2001:0db8::0001這是不行的,必須寫成2001:db8::1。

4.2. "::" Usage
The use of the symbol "::" MUST be used to its maximum capability. The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field.
表示式必須盡可能的簡化,而且只有一個"0000"時不能簡化。所以2001:db8:0:0:0:0:2:1是不正確的,應該被寫成2001:db8::2:1。而2001:db8::1:1:1:1:1卻是不正確的,應該被寫成2001:db8:0:1:1:1:1:1。
When there is an alternative choice in the placement of a "::", the longest run of consecutive 16-bit 0 fields MUST be shortened. When the length of the consecutive 16-bit 0 fields are equal, the first sequence of zero bits MUST be shortened.
簡而言之,就是如果有兩個可以簡化::的地方,挑表示式最小,如果都是最小,則挑第一個位置。如2001:0:0:1:0:0:0:1必須被簡化為2001::1:0:0:0:1。

4.3. Lowercase
用小寫表示之。


5. Text Representation of Special Addresses


IPv4-Mapped IPv6 addresses [RFC5214]的寫法要符合前面的規則,且後面為IPv4寫法,如0:0:0:0:0:ffff:192.0.2.1應該被寫成::ffff:192.0.2.1。


6. Notes on Combining IPv6 Addresses with Port Numbers


以下是一般結合port的寫法:
  • [2001:db8::1]:80
  • 2001:db8::1:80
  • 2001:db8::1.80
  • 2001:db8::1 port 80
  • 2001:db8::1p80
  • 2001:db8::1#80

建議使用第一種寫法[2001:db8::1]:80





2013年5月26日 星期日

Packet Filtering HOWTO 讀後筆記II


原文:Packet Filtering HOWTO


Packet Filtering HOWTO 讀後筆記I



7. Using iptables


Extensions to iptables: New Matches
iptables具備可擴充性(extensible),這表示我們可以在kernel或是iptable上新增新的功能。目前kernel和iptables已經具備許多的標準擴充功能,您可以在kernel/net/netfilter目錄底下看到許多的xt_XXX.c。在iptables也會有相對應的extensions,在extensions/libxt_XXX.c,iptables的extensions會被build成shared library,需要使用-m將extensions載入。如果要取得extensions('-p'的說明,只要在後面加上-h或是--help即可。
# iptables -p tcp --help
iptables v1.4.12

Usage: iptables -[ACD] chain rule-specification [options]
       iptables -I chain [rulenum] rule-specification [options]
       iptables -R chain rulenum rule-specification [options]
       iptables -D chain rulenum [options]
       iptables -[LS] [chain [rulenum]] [options]
       iptables -[FZ] [chain] [options]
       iptables -[NX] chain
       iptables -E old-chain-name new-chain-name
       iptables -P chain target [options]
       iptables -h (print this help information)

Commands:
Either long or short options are allowed.
  --append  -A chain            Append to chain
  --check   -C chain            Check for the existence of a rule
  --delete  -D chain            Delete matching rule from chain
  --delete  -D chain rulenum
                                Delete rule rulenum (1 = first) from chain
  --insert  -I chain [rulenum]
                                Insert in chain as rulenum (default 1=first)
  --replace -R chain rulenum
                                Replace rule rulenum (1 = first) in chain
  --list    -L [chain [rulenum]]
                                List the rules in a chain or all chains
  --list-rules -S [chain [rulenum]]
                                Print the rules in a chain or all chains
  --flush   -F [chain]          Delete all rules in  chain or all chains
  --zero    -Z [chain [rulenum]]
                                Zero counters in chain or all chains
  --new     -N chain            Create a new user-defined chain
  --delete-chain
            -X [chain]          Delete a user-defined chain
  --policy  -P chain target
                                Change policy on chain to target
  --rename-chain
            -E old-chain new-chain
                                Change chain name, (moving any references)
Options:
    --ipv4      -4              Nothing (line is ignored by ip6tables-restore)
    --ipv6      -6              Error (line is ignored by iptables-restore)
[!] --proto     -p proto        protocol: by number or name, eg. `tcp'
[!] --source    -s address[/mask][...]
                                source specification
[!] --destination -d address[/mask][...]
                                destination specification
[!] --in-interface -i input name[+]
                                network interface name ([+] for wildcard)
 --jump -j target
                                target for rule (may load target extension)
  --goto      -g chain
                              jump to chain with no return
  --match       -m match
                                extended match (may load extension)
  --numeric     -n              numeric output of addresses and ports
[!] --out-interface -o output name[+]
                                network interface name ([+] for wildcard)
  --table       -t table        table to manipulate (default: `filter')
  --verbose     -v              verbose mode
  --line-numbers                print line numbers when listing
  --exact       -x              expand numbers (display exact values)
[!] --fragment  -f              match second or further fragments only
  --modprobe=          try to insert modules using this command
  --set-counters PKTS BYTES     set the counter during insert/append
[!] --version   -V              print package version.

tcp match options:
[!] --tcp-flags mask comp       match when TCP flags & mask == comp
                                (Flags: SYN ACK FIN RST URG PSH ALL NONE)
[!] --syn                       match when only SYN flag set
                                (equivalent to --tcp-flags SYN,RST,ACK,FIN SYN)
[!] --source-port port[:port]
 --sport ...
                                match source port(s)
[!] --destination-port port[:port]
 --dport ...
                                match destination port(s)
[!] --tcp-option number        match if TCP option set



Other Match Extensions
mac 這個module必須用'-m mac''--match mac'載入,用於比對source MAC,只能用於PREOUTING和INPUT這兩個chain。
limit 這個module必須用'-m limit''--match limit'載入,用於限制match的速率。--limit單位可以是/second、/minute、/hour或是/day,如5/s,每秒5個。--limit-burstnumber to match in a burst。用下圖來描述這兩者的涵義

limit-burst就是水桶的容量,limit就是水桶流出的流量,當packet裝滿水桶,後面的就會被丟棄,隨著時間過去,水桶會流出lmit個packet,就是可以再允許limit流進水桶。

7.4 Target Specifications
何謂target?what to do to the packets which match our tests. This is called a rule's target.(當match我們的條件之後,所要採取的動作就稱為rule的target)。target也可以是User-defined chains。

iptables是first match,packet進入INPUT這個chain後,會由第一條rule開始比對,如果比對成功並且有明確的target(ACCRPT/DROP)就會執行丟棄/同意packet並且終止比對,當target是另外一個chain時,就會jump到該chain中繼續進行比對,如果都沒有match,就會再回到原來的chain中繼續往下比對。
# iptables -A INPUT -p icmp
# iptables -A INPUT -p icmp -j LOG
# iptables -A INPUT -p icmp -j ACCEPT
# iptables -L -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

    0     0            icmp --  any    any     anywhere             anywhere

    0     0 LOG        icmp --  any    any     anywhere             anywhere
         LOG level warning
    0     0 ACCEPT     icmp --  any    any     anywhere             anywhere


Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination


Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

# ping 127.0.0.1 -c 1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
[ 6975.682678] IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.
0.0.1 DST=127.0.0.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=ICMP TYPE=8 C
ODE=0 ID=4908 SEQ=0
[ 6975.697694] IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.
0.0.1 DST=127.0.0.1 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=49768 PROTO=ICMP TYPE=0
CODE=0 ID=4908 SEQ=0
64 bytes from 127.0.0.1: seq=0 ttl=64 time=34.397 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 34.397/34.397/34.397 ms
# iptables -L -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination

    2   168            icmp --  any    any     anywhere             anywhere

    2   168 LOG        icmp --  any    any     anywhere             anywhere
         LOG level warning
    2   168 ACCEPT     icmp --  any    any     anywhere             anywhere


Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination


Chain OUTPUT (policy ACCEPT 2 packets, 168 bytes)
 pkts bytes target     prot opt in     out     source               destination

Extensions to iptables: New Targets
還有LOG、REJECT、RETURN和QUEUE等target。詳細用法請自行參考該page。




2013年5月25日 星期六

Packet Filtering HOWTO 讀後筆記I


原文:Packet Filtering HOWTO



3 What is a packet filter?


packet filter是一套軟體,會根據packet的header決定這個packet的命運,可能是ACCEPT(bypass)或是DROP,或是其他複雜的操作(NAT/QUEUE/LOG)。

3.2 How Do I Packet Filter Under Linux?
在Linux 1.1就有packet filtering功能,在1994年由Alan Cox根據BSD的ipfw移植過來,經過Jos Vos和其他人的努力,在1999年的Linux 2.4研發出第四代tool"iptables"使用至今。
iptables可以隨時的新增或刪除在kernel中的packet filtering table的rule,每當重新開機後,這些rule就會消失,您可以使用iptables-save/iptables-restore將這些rule存到檔案,或由檔案回存到kernel中。

6. How Packets Traverse The Filters


"filter"這個table有三個chain,分別是"INPUT""OUTPUT""FORWARD"。如下圖:

當packet傳入(incoming),會先經過Routing Decision,決定封包的去向(Local In/Forwarding/Drop),當封包經過filter的這三個chain的任何一個,都會進行rule的比對並且決定封包的去留,如果是Drop,就會立刻丟棄封包,如果是ACCEPT就會往下一個rule進行比對( `if the packet header looks like this, then here's what to do with the packet')。每一個chain都有所謂的default policy,當所有的rule在這個chain都不match,就會執行這個policy(DROP/ACCEPT)。

7. Using iptables


filter table內建的三個chain INPUT、OUTPUT和FORWARD是不能被刪除的,這裡有幾個對China進行操作的選項
  1. 新增一個chain / Create a new chain (-N).
  2. 刪除空白的chain / Delete an empty chain (-X).
  3. 改變內建的chain的policy / Change the policy for a built-in chain. (-P).
  4. 列出chain的rule / List the rules in a chain (-L).
  5. 清除所有在chain中的rule / Flush the rules out of a chain (-F).
  6. 清除chain中rule的counter / Zero the packet and byte counters on all rules in a chain (-Z).

以下是對rule進行操作的選項:
  1. 新增rule到chain的後面 / Append a new rule to a chain (-A).
  2. 插入rule到chain的某個位置 / Insert a new rule at some position in a chain (-I).
  3. 取代chain中某個rule / Replace a rule at some position in a chain (-R).
  4. 移除chain中某個rule / Delete a rule at some position in a chain, or the first that matches (-D).


7.2 Operations on a Single Rule
最常用到的就是append(-A)和delete(-D) rule到chain中,當然還有insert(-I)和replace(-R)。每一條rule基本上就是設定一些條件和target,當packet滿足這些條件,就會執行該target,可能是ACCEPT也可能是DROP。比如,我們要將source ip是127.0.0.1的ICMP做DROP:
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
# iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
#

[!] -s, --source address[/mask][,...] source address,除了可以使用IP以外,也可以是hostname,不過只有在設定的當下會做一次resolved。
[!] -p, --protocol protocol 可以是tcp、udp、udplite、icmp、esp、ah、sctp或是all,也可以是 /etc/protocols裡面的名稱,或是任何數值。
-j, --jump target This specifies the target of the rule; i.e., what to do if the packet matches it. Target也可以是 user-defined chain。
每個選項前面都可以加上!表示反向的意思。

要刪除之前設定的rule可以使用
iptables -D INPUT 1

或是
iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP

第一種是刪除第一條rule,第二種是刪除符合-s 127.0.0.1 -p icmp -j DROP這個condition的rule。

常用的option還有:
[!] -i, --in-interface name packet由哪個interface收到,只能套用在INPUT、FORWARD和PREROUTING這些chain,interface name以+為結尾就表示pattern比對。如-i ppp+就會比對所有ppp開頭的interface。
[!] -o, --out-interface name packet會由哪個interface送出,只能套用在FORWARD、OUTPUT和POSTROUTING這些chain,同樣可以使用+



2013年5月1日 星期三

6 sigma上課筆記 - Interactions Plot


人視視覺上的動物,所以由圖形上來了解趨勢會比一堆數據來的容易些,在6 sigma上課筆記 - 二維表格轉Minitab格式 中,我們想知道Temp和Press對yeild有哪什麼影響,正交互作用?逆交互作用?以及有沒有交互作用?
在Minitab中可以用Interactions Plot功能來判斷。基本判斷方法:如果圖形呈現平行,就是沒有交互作用。如果圖形呈現不對稱(有增強作用)或交叉(互逆作用),就是有交互作用。
Stat > ANOVA > Interactions Plot



由圖可知有交互作用。


6 sigma上課筆記 - 二維表格轉Minitab格式


上課的時候老師有說到,我們常常拿到的表格是二維的,最好把他轉成統計上常用的格式Stack Rows(switch rows to columns),為什麼要這種格式呢?因為這樣如果增加實驗因子,整個表格不會有太大變動。
假設實驗數據如下:



我們可以在Minitab 14中執行Data > Stack > Rows


因為Press 1/Press 2這兩column的資料是要堆疊的,所以放置在to be stacked。
Store stacked data in是堆疊後的資料,我們放在下一個空白的 column,並且命名為yield。
Store column subscripts in是column這個factor,我們是Press 1/Press 2,所以我們命名為Press。
Expand the following columns while stacking rows就是row這個factor,我們是Temp 1/Temp 2,所以我們命名為Temp。


最後就是跑出來的worksheet了





2012年8月4日 星期六

An Introduction To The SQLite C/C++ Interface


為了能夠用SQL將資料由資料庫撈出,我們必須認識兩個主要的Object:
  1. The database connection object:sqlite3
  2. 執行sqlite3_open()之後,就會得到該object,感覺類似open之後的file descriptor。
  3. The prepared statement object:sqlite3_stmt
  4. 把SQL轉成bytecode,但是還沒真正被執行。請參考Compiling An SQL Statement/To execute an SQL query, it must first be compiled into a byte-code program using one of these routines.
    An instance of this object represents a single SQL statement. This object is variously known as a "prepared statement" or a "compiled SQL statement" or simply as a "statement".


一個常見的SQLite pattern為:
  1. sqlite3_open():取得database connection object。
  2. sqlite3_preapre() :取得prepared statement object。
  3. sqlite3_step():執行prepared statement object。
  4. sqlite3_column_<type>():將sqlite回傳回來的資料,轉成對應的type取出。
  5. sqlite3_finalize():釋放prepared statement object。
  6. sqlite3_close():釋放database connection object。


#include <iostream>
#include <sqlite3.h>
#include <cstdlib>
#include <assert.h>

using namespace std;

int main(int argc, char** argv)
{
  sqlite3 *conn;
  sqlite3_stmt *statement; // SQL Statement Object
  int ret = 0;
  int cols;

  // This routine opens a connection to an SQLite database file
  //  and returns a database connection object.
  ret = sqlite3_open_v2("hello.db", &conn, SQLITE_OPEN_READONLY, NULL);
  if (ret) {
    cout << "can not open database\n";
    exit(0);
  }

  ret = sqlite3_prepare_v2(conn, "select * from hello", -1, &statement, NULL);
  if (ret != SQLITE_OK) {
    cout << "We did not get any data\n";
    exit(0);
  }

  cols = sqlite3_column_count(statement);

  for (int col = 0; col < cols; col++) {
    cout << " " << sqlite3_column_name(statement, col);
  };
  cout << endl;

  while (true) {
    ret = sqlite3_step(statement);
    if (ret == SQLITE_ROW) {
      for (int col = 0; col < cols; col++) {
        switch (sqlite3_column_type(statement, col)) {
          case SQLITE_INTEGER:
            cout << " " << sqlite3_column_int(statement, col) << " ";
            break;
          case SQLITE_FLOAT:
            cout << " " << sqlite3_column_double(statement, col) << " ";
            break;
          case SQLITE_TEXT:
            cout << " " << sqlite3_column_text(statement, col) << " ";
            break;
          case SQLITE_NULL:
            cout << " " << "NULL" << " ";
            break;
        }
      };
      cout << endl;
    } else if (ret == SQLITE_DONE) {
      cout << "done" << endl;
      break;
    } else {
      cout << "ret:" << ret << endl;
      break;
    }
  }

  sqlite3_finalize(statement);
  sqlite3_close(conn);

  return 0;
}


sqlite3_exec()是將sqlite3_prepare_v2(), sqlite3_step()和 sqlite3_finalize()包裝起來的API,其原型為
int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
  void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

  • 第二個參數要執行的SQL statement。
  • 第三個參數是callback function。每一個row都會呼叫該callback一次。
  • 第四個參數是要傳給callback function的data。
  • 第五個參數就是發生錯誤時,儲存錯誤資訊的指標。
因此上面的程式可以改寫為
#include <iostream>
#include <sqlite3.h>

using namespace std;

int callback(void *data, int column, char **value, char **name)
{
  int i;
  cout << (char *)data << endl;
  for (i = 0; i < column; i++) {
    cout << name[i] << ":" << (value[i] ?: "NULL") << endl << flush;
  }
  return 0;
}


int main(int argc, char** argv)
{
  sqlite3 *conn;
  int ret = 0;
  char *errmsg = NULL;
  char data[] = "brook";

  // This routine opens a connection to an SQLite database file
  //  and returns a database connection object.
  ret = sqlite3_open_v2("hello.db", &conn, SQLITE_OPEN_READONLY, NULL);
  if (ret != SQLITE_OK) {
     cout << sqlite3_errmsg(conn) << ".(" << ret << ")" << endl;
     exit(0);
  }

  ret = sqlite3_exec(conn, "select * from hello", callback, data, &errmsg);
  if (ret != SQLITE_OK) {
     cout << "We did not get any data. " << errmsg << endl;
     sqlite3_free(errmsg);
  }

  sqlite3_close(conn);

  return 0;
}






2012年7月28日 星期六

Introduction SQLite


大家比較耳熟能詳的database大多是client/server的架構居多,如:MySQL、PostgreSQL、MS-SQL和Oracle等等,而SQLite感覺比較像MS的Access, 程式本身就負責開啟資料庫並且直接操作,更多的資訊可以參考官網http://www.sqlite.org/

以下就個人在SQLite網站看到的介紹,寫下一些筆記。
About SQLite
SQLite不像許多SQL資料庫有分開的Server process。SQLite直接對資料庫檔案做存取,這些資料庫檔案室可以跨平台的, 意味著您可以直接在32/64和big-endian/little-endian複製這些資料庫檔案,都能正確地被SQLite所存取。

Appropriate Uses For SQLite/Situations Where Another RDBMS May Work Better SQLite因為直接對database做存取,所以多個client同時對某database做存取可能會有問題。 如果是高流量(High-volume Websites)或是高資料量(Very large datasets)都不適合SQLite,畢竟它是拿來給embedded用的。

總體而言,對於小資料庫的應用SQLite已經是非常好的選擇了。


基本操作
brook:~$ ls hello.db
ls: cannot access hello.db: No such file or directory
brook:~$ sqlite hello.db
Loading resources from /home/brook/.sqliterc
SQLite version 2.8.17
Enter ".help" for instructions
sqlite> .help
.databases             List names and files of attached databases
.dump ?TABLE? ...      Dump the database in a text format
.echo ON|OFF           Turn command echo on or off
.exit                  Exit this program
.explain ON|OFF        Turn output mode suitable for EXPLAIN on or off.
.header(s) ON|OFF      Turn display of headers on or off
.help                  Show this message
.indices TABLE         Show names of all indices on TABLE
.mode MODE             Set mode to one of "line(s)", "column(s)",
                       "insert", "list", or "html"
.mode insert TABLE     Generate SQL insert statements for TABLE
.nullvalue STRING      Print STRING instead of nothing for NULL data
.output FILENAME       Send output to FILENAME
.output stdout         Send output to the screen
.prompt MAIN CONTINUE  Replace the standard prompts
.quit                  Exit this program
.read FILENAME         Execute SQL in FILENAME
.schema ?TABLE?        Show the CREATE statements
.separator STRING      Change separator string for "list" mode
.show                  Show the current values for various settings
.tables ?PATTERN?      List names of tables matching a pattern
.timeout MS            Try opening locked tables for MS milliseconds
.width NUM NUM ...     Set column widths for "column" mode

sqlite> .tables
sqlite> create table hello (x integer PRIMARY KEY ASC, y);
sqlite> .tables
hello
sqlite> insert into hello (y) values('a');
sqlite> insert into hello (y) values(10);
sqlite> insert into hello (y) values(datetime('now'));
sqlite> select * from hello;
x           y
----------  ----------
1           a
2           10
3           2012-07-30
sqlite> .quit


我們也可以直接在command line上面執行sqlite
brook:~$ sqlite hello.db .dump
Loading resources from /home/brook/.sqliterc
BEGIN TRANSACTION;
create table hello (x integer PRIMARY KEY ASC, y);
INSERT INTO hello VALUES(1,'a');
INSERT INTO hello VALUES(2,10);
INSERT INTO hello VALUES(3,'2012-07-30 04:20:12');
COMMIT;
brook:~$ sqlite hello.db "select * from hello"
Loading resources from /home/brook/.sqliterc
x           y
----------  ----------
1           a
2           10
3           2012-07-30
brook:~$ cat ~/.sqliterc
.mode column
.header on
.nullvalue NULL

更多SQL語法請參考http://www.sqlite.org/lang.html





2012年6月30日 星期六

Pipe to a Subprocess


偶爾想偷懶的我會在code中使用system(),呼叫shell來執行一些東西,並且將執行完的結果丟回來程式中處理,這時候popen就很好用了,popen - pipe stream to or from a process。
popen允許開啟read或write pipe,不能夠同時開啟為read/write,read可以讓程式從popen中讀回來處理,而write可以將程式中的資料丟到popen處理。

popen(,"r")
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    char buf[128];
    float a, b, c, d;
    FILE *fp;
    if ((fp = popen("(df -h 2>/dev/null) | tail -n +2", "r")) == NULL) {
        fprintf(stderr, "popen() failed\n");
        return -1;
    }
    while (!feof(fp)) {
        fscanf(fp, "%*[^ ]%f%*[^1-9]%f%*[^1-9]%f%*[^1-9]%f%%%*[^\n]", &a, &b, &c, &d);
        printf("%f/%f/%f/%f\n", a, b, c, d);
    }
    return 0;
}


popen(,"w")
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    char buf[] = "1 2 3 4 5";
    float a, b, c, d;
    FILE *fp;
    if ((fp = popen("xargs -n 1 > /tmp/xx", "w")) == NULL) {
        fprintf(stderr, "popen() failed\n");
        return -1;
    }
    fprintf(fp, "%s", buf);
    pclose(fp);
    return 0;
}


    參考資料:
  • The GNU C Library, Chapter 15.2




2012年5月26日 星期六

Design Patterns - Command pattern


Command pattern是一種將Action封裝起來,並提供一個general的interface作為呼叫時(invoke)的統一介面。

舉個生活例子來說明,想必您一定用過萬用遙控器,User可以設定遙控器上某個按鈕1的功能為電視的開關,所以當User按下按鈕1,就可以開關電視,接著User設定按鈕2為控制冷氣的開關,所以當User按下按鈕2,就可以開關冷氣,這樣簡單的運作就是一種Command Pattern。
電視開關是一種Action,被封裝成遙控器上面的按鈕,對User來說,這是一個General的interface,而且User在變更任和按鈕功能時,並不會影響遙控器上面的其他按鈕。

Command pattern有三個名詞需要解釋一下:
client:The client instantiates the command object and provides the information required to call the method at a later time.
invoker: The invoker decides when the method should be called.
receiver: The receiver is an instance of the class that contains the method's code.

client就可以想成"設定按鈕"的動作,invoker就是User了,而receiver就是電器了。

圖取自http://en.wikipedia.org/wiki/Command_pattern.


#include <iostream>

class Command {
public:
    virtual int exec(void *args) = 0;
};

// Receiver
class TV {
    bool turn_on_off;
public:
    void pwr_switch() {
        if (turn_on_off) {
            std::cout << "Turn off TV" << std::endl;
        } else {
            std::cout << "Turn on TV" << std::endl;
        }
        turn_on_off = !(turn_on_off);
    }
};

class CmdTvSwitch: public Command {
    TV *_tv;
public:
    CmdTvSwitch(TV *tv) {
        this->_tv = tv;
    }
    virtual int exec(void *args) {
        this->_tv->pwr_switch();
        return 0;
    }
};

int main(int argc, char *argv[])
{
    // Client
    TV tv;
    Command  *c;
    c = new CmdTvSwitch(&tv);
    c->exec(NULL);
    c->exec(NULL);
    return 0; 
}

就目前個人在使用這個Pattern上面的感觸就是"Command pattern是一種將Action封裝起來,並提供一個general的interface作為呼叫時(invoke)的統一介面。"比如,我在寫Message Queue會用到,提供新的指令供外界呼叫也會用到。
    參考資料:
  1. http://en.wikipedia.org/wiki/Command_pattern
  2. http://caterpillar.onlyfun.net/Gossip/DesignPattern/CommandPattern.htm




2012年5月19日 星期六

理財常用的Link



股匯市原物料期貨報價, http://www.stockq.org/
全球股市排行榜, http://www.stockq.org/market/
貨幣各國匯率歷史紀錄, http://fxtop.com/en/historates.php
金磚四國和台灣股市走勢圖, http://finance.yahoo.com
台灣地區銀行利率, http://www.taiwanrate.com/
台灣地區各網路銀行入口, http://www.easyatm.com.tw/playatm.html
文茜世界財經週報, http://www.youtube.com
57金錢爆, http://www.youtube.com
國際主要股市月報 , http://www.twse.com.tw/ch/statistics/statistics.php
基金績效,
台股上市公司本益比, http://www.twse.com.tw
台股上櫃公司本益比, http://www.otc.org.tw
基金定期定額試算, http://fund.scsb.com.tw
STOCK-AI提供各類經濟指標數據, https://stock-ai.com/
blog
法意聯盟, http://www.wretch.cc/blog/joejoejoe



持續更新中...



2012年4月7日 星期六

常用的regular expression


這篇會慢慢增加內容,所以我也會更新發布日期。
JavaScript
    var mac = /^\s*([\d[a-f]{2}:){5}[\d[a-f]{2}\s*$/i;
    var ip = /^((\d)|(([1-9])\d)|(1\d\d)|(2(([0-4]\d)|5([0-5]))))\.((\d)|(([1-9])\d)|(1\d\d)|(2(([0-4]\d)|5([0-5]))))\.((\d)|(([1-9])\d)|(1\d\d)|(2(([0-4]\d)|5([0-5]))))\.((\d)|(([1-9])\d)|(1\d\d)|(2(([0-4]\d)|5([0-5]))))$/;


C language
    char *mac =  "([[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}";
    char *ip = "^(([0-9])|(([1-9])[0-9])|(1[0-9][0-9])|(2(([0-4][0-9])|5([0-5]))))\\.(([0-9])|(([1-9])[0-9])|(1[0-9][0-9])|(2(([0-4][0-9])|5([0-5]))))\\.(([0-9])|(([1-9])[0-9])|(1[0-9][0-9])|(2(([0-4][0-9])|5([0-5]))))\\.(([0-9])|(([1-9])[0-9])|(1[0-9][0-9])|(2(([0-4][0-9])|5([0-5]))))$";


    參考資料
  1. http://en.wikipedia.org/wiki/Regular_expression



2012年4月1日 星期日

頁面遮罩


我們常常可以在Web上看到,當有事件在背景執行時,Web會跳出半透明的視窗遮住後面的頁面,如:


這裡主要是利用JavaScript控制layer(Z-Index),以及style的opacity和style的display達成,layer控制element之間的stack,也就是MS office裡面常常提到的,"往上/下一層",style.opacity則是透明度,style.display控制顯示或隱藏,這些就可以達成頁面遮罩的功能了。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <script type="text/javascript">
//<![CDATA[
    function show() {
      document.getElementById("xie").style.display = "";
      document.getElementById("content1").style.display = "";
      document.getElementById("content1").innerHTML = "內容<br/><input onclick='hide()' type='button' value='確定'/>";
    }

    function hide() {
      document.getElementById("xie").style.display = "none";
      document.getElementById("content1").style.display = "none";
    }
  //]]>
  </script>
  <title>JavaScript Mask</title>
</head>

<body>
  <div style=
  "filter:alpha(opacity=50); -moz-opacity:0.5; opacity: 0.5; width: 100%; background-color: White; display: none; height: 100%; position: absolute; left: 0; top: 0;"
       id="xie"></div>

  <div style=
  "width: 100px; background-color: Red; display: none; height: 53px; position: absolute; left: 144px; top: 100px;"
       id="content1"></div>

  <input onclick="show()" type="button" value="顯示" />
</body>
</html>





2012年3月24日 星期六

動態產生HTML element -- document.createElement


我們可以利用document.createElement()動態的產生HTML的element,再利用Node.appendChild()插入某個Node底下,或利用Node.removeChild()自某個Node底下移除,更多資訊可以參考[1]。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title>auto table</title>
</head>

<body>
  <table id="brook" summary=""></table>
  <script type="text/javascript">
  //<![CDATA[
    function create_new_row_button(eT, msg) {
        var eR = document.createElement("tr");
        var eC = document.createElement("td");
        var eB = document.createElement("input");
        eB.type = "button"
        eB.value= msg;
        eB.style.width = "100px";

        eT.appendChild(eR);
        eR.appendChild(eC);
        eC.appendChild(eB);
    }
    var station = [
        {name: "CHT"},
        {name: "TW"},
    ];
    for (var i = 0; i < station.length; i++) {
        create_new_row_button(document.getElementById("brook"),
                              station[i].name);
    }
  //]]>
  </script>
</body>
</html>






2012年3月3日 星期六

glibc讀書心得 -- Ch2 Error Reporting


在glibc中會去偵錯並且回傳錯誤值,通常我們都應該去檢查這些回傳值,並且作error-handling,比如開檔 open()/fopen(),並非每次都會開成功,所以,open()/fopen()通常都會去檢查return value是不是有正確。

2.1 Checking for Errors
glibc的return value通常是-1、NULL或是EOF,這只能知道錯誤發生,至於發生何種錯誤,都是存在errno這個變數中,當您要使用errno必須include <errno.h>。這個header file也定義很多error code,都是以E為開頭,這些error code在Ch 2.2中有說明,用到再查就OK啦。

2.2 Error Codes
這個章節主要說明定義的error code,值得注意的是EAGAIN和EWOULDBLOCK的值一樣,所以不能放在同一個case switch中,其實我常用的error code大概只有他列的1/5不到吧,看看就好。

2.3 Error Messages 基本上我們都是希望report的錯誤是文字型態,而不是只有error code,所以glibc有提供一些轉換的function:
char * strerror(int errnum)[Function]
char * strerror_r(int errnum, char *buf, size t n)[Function]
void perror(const char *message)[Function]
char * program_invocation_name[Variable]
char * program_invocation_short_name[Variable]
void error (int status, int errnum, const char *format, . . . )[Function]
error_at_line (int status, int errnum, const char *fname,unsigned int lineno, const char *format, . . . )[Function]

char * strerror(int errnum)
將errnum轉成相對應的字串
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    printf("%s\n", strerror(EINTR));
    // print out "Interrupted system call"
    return 0;
}

char * strerror_r(int errnum, char *buf, size t n)
strerror的reentrant版本,mutli-thread就一定要用這個版本。
#define _GNU_SOURCE
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    char buf[32];
    printf("%s\n", strerror_r(EINTR, buf, sizeof(buf)));
    // print out "Interrupted system call"
    return 0;
}

void perror(const char *message)
效果和printf(stderr, "%s:%s", message, strerror(errno))相似,把error message寫到stderr去,接著冒號後面再接errno的message。
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    perror("my_perror_msg1");
    // print out "my_perror_msg1: Success"
    errno = EINTR;
    perror("my_perror_msg2");
    // print out "my_perror_msg2: Interrupted system call"
    return 0;
}

char * program_invocation_name / char * program_invocation_short_name
該程式的名稱,和argv[0]的值一樣。
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    printf("%s\n", argv[0]);
    // print out "./a.out"
    printf("%s\n", program_invocation_name);
    // print out "./a.out"
    printf("%s\n", program_invocation_short_name);
    // print out "a.out"
    return 0;
}


void error (int status, int errnum, const char *format, . . . )
status不為0時,就等同exit(status),後面的參數errnum和format用途類似perror(),當errnum為0時,就不會印後面的message,但是perror()會印Success。
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    error(0, 0, "%s", "msg");
    error(0, EINTR, "%s", "msg");
    // print out "./a.out: msg: Interrupted system call"
    error(1, EINTR, "%s", "msg");
    // print out "./a.out: msg: Interrupted system call" and exit(1)
    return 0;
}


error_at_line(int status, int errnum, const char *fname, unsigned int lineno, const char *format, ...)
error_at_line()和error()很像,只是多了fname和lineno印出檔案名稱和行號。
#include <stdio.h>
#include <errno.h>  // EINTR
#include <string.h> // strerror()

int main(int argc, char *argv[])
{
    error_at_line(0, 0, __FILE__, __LINE__, "%s", "msg");
    // print out "./a.out:error_at_line.c:7: msg"
    error_at_line(0, EINTR, __FILE__, __LINE__, "%s", "msg");
    // print out "./a.out:error_at_line.c:8: msg: Interrupted system call"
    error_at_line(1, EINTR, __FILE__, __LINE__, "%s", "msg");
    // print out "./a.out:error_at_line.c:11: msg: Interrupted system call"
    return 0;
}



    參考資料:
  • The GNU C Library, Chapter 2



IE8無法下載檔案


話說有一天,我用Luci寫一段download動態產生的檔案時,發生部分的IE8下載有問題,都會產生無法下載的訊息,當然就是立刻請問google大神,尋得此文章[PHP]下載檔案時無法直接開啟文件的解法方法,雖然是用PHP寫,不過小改一下就可以在Luci上面如法炮製啦。

[PHP]下載檔案時無法直接開啟文件的解法方法
header("Content-Type: application/octetstream; name=$FILEname"); //for IE & Opera
header("Content-Type: application/octet-stream; name=$FILEname"); //for the rest
header("Content-Disposition: attachment; filename=$FILEname;");
header("Content-Transfer-Encoding: binary");
header("Cache-Control: cache, must-revalidate");
header("Pragma: public");
header("Expires: 0");


Luci不過就是改呼叫luci.http.header()。
[Luci]下載檔案時無法直接開啟文件的解法方法
luci.http.header("Content-Type", "application/octetstream; name=" .. fname); //for IE & Opera
luci.http.header("Content-Type", "application/octet-stream; name=" .. fname); //for the rest
luci.http.header("Content-Disposition", "attachment; filename=" .. fname);
luci.http.header("Content-Transfer-Encoding", "binary");
luci.http.header("Cache-Control", "cache, must-revalidate");
luci.http.header("Pragma", "public");
luci.http.header("Expires", "0");




2012年2月26日 星期日

glibc讀書心得 -- Ch1 Introduction


1.1 Getting Started
C語言並沒有內建一些常用的操作,如input/output、memory management等等,這些通通被定義在Standard Library中(glibc)。

1.2 Standards and Portability
glibc參考的C Library標準有ISO C(American National Standard X3.159-1989—“ANSI C” and later by the International Standardization Organization (ISO): ISO/IEC 9899:1990, “Programming languages—C”.)和POSIX兩個。以及參考System V和Berkeley UNIX兩個實做而成。

1.3 Using the Library
Library在C主要由兩個部份組成:
  1. header files that define types and macros and declare variables and functions
  2. the actual library or archive that contains the definitions of the variables and functions.
為了能使用glibc,你必須將所需的header file,用#include這個preprocessor directive將其引入,嚴格來說,您可以不必include這些header file,只要您可以正確的宣告相關的變數、巨集等等,不過為了效率和能正確的宣告相關變數,我們都會採用header file的形式,將其引入(include)。至於Macro的部份就參考我之前的C preprocessor的文章GCC - C Preprocessor應該會更清楚。
關於Reserved Names個人覺得還蠻重要的,就直接貼出來了:
  1. Names beginning with a capital ‘E’ followed a digit or uppercase letter may be used for additional error code names. See Chapter 2 [Error Reporting], page 13.
  2. Names that begin with either ‘is’ or ‘to’ followed by a lowercase letter may be used for additional character testing and conversion functions. See Chapter 4 [Character Handling], page 65.
  3. Names that begin with ‘LC_’ followed by an uppercase letter may be used for additional macros specifying locale attributes. See Chapter 7 [Locales and Internationalization], page 150.
  4. Names of all existing mathematics functions (see Chapter 19 [Mathematics], page 466) suffixed with ‘f’ or ‘l’ are reserved for corresponding functions that operate on float and long double arguments, respectively.
  5. Names that begin with ‘SIG’ followed by an uppercase letter are reserved for additional signal names. See Section 24.2 [Standard Signals], page 592.
  6. Names that begin with ‘SIG_’ followed by an uppercase letter are reserved for additional signal actions. See Section 24.3.1 [Basic Signal Handling], page 600.
  7. Names beginning with ‘str’, ‘mem’, or ‘wcs’ followed by a lowercase letter are reserved for additional string and array functions. See Chapter 5 [String and Array Utilities], page 73.
  8. Names that end with ‘_t’ are reserved for additional type names.


    參考資料:
  1. The GNU C Library, Chapter 1




2012年1月29日 星期日

JSON-C


JSON-C是一套用C寫的JSON format的parser和generator,可以將JSON字串正確parse,並且存成json_object進行操作(新增/刪除/修改),也可以將json_object轉成JSON字串,個人還蠻推薦的。

官方網站:JSON-C

安裝步驟
brook@vista:~/src$ git clone https://github.com/json-c/json-c.git json-c
Cloning into json-c...
remote: Counting objects: 448, done.
remote: Compressing objects: 100% (169/169), done.
remote: Total 448 (delta 315), reused 405 (delta 274)
Receiving objects: 100% (448/448), 125.68 KiB | 76 KiB/s, done.
Resolving deltas: 100% (315/315), done.
brook@vista:~/src$ cd json-c/
brook@vista:~/src/json-c$ ./autogen.sh
autoreconf: Entering directory `.'
autoreconf: configure.in: not using Gettext
autoreconf: running: aclocal 
autoreconf: configure.in: tracing
autoreconf: running: libtoolize --install --copy
libtoolize: Consider adding `AC_CONFIG_MACRO_DIR([m4])' to configure.in and
libtoolize: rerunning libtoolize, to keep the correct libtool macros in-tree.
libtoolize: Consider adding `-I m4' to ACLOCAL_AMFLAGS in Makefile.am.
autoreconf: running: /usr/bin/autoconf
autoreconf: running: /usr/bin/autoheader
autoreconf: running: automake --add-missing --copy --no-force
autoreconf: Leaving directory `.'
brook@vista:~/src/json-c$ ./configure
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
...
brook@vista:~/src/json-c$ make
make  all-am
make[1]: Entering directory `/home/brook/src/json-c'
/bin/bash ./libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.    -Wall -Wwrite-strings -Werror -std=gnu99 -D_GNU_SOURCE -D_REENTRANT -g -O2 -MT arraylist.lo -MD -MP -MF .deps/arraylist.Tpo -c -o arraylist.lo arraylist.c
...
brook@vista:~/src/json-c$ make check
make  test1 test2 test4 test_parse_int64 test_null test_cast
make[1]: Entering directory `/home/brook/src/json-c'
gcc -DHAVE_CONFIG_H -I.    -Wall -Wwrite-strings -Werror -std=gnu99 -D_GNU_SOURCE -D_REENTRANT -g -O2 -MT test1.o -MD -MP -MF .deps/test1.Tpo -c -o test1.o test1.c
test1.c: In function ‘sort_fn’:
test1.c:14:8: error: assignment discards ‘const’ qualifier from pointer target type [-Werror]
test1.c:15:8: error: assignment discards ‘const’ qualifier from pointer target type [-Werror]
cc1: all warnings being treated as errors

make[1]: *** [test1.o] Error 1
make[1]: Leaving directory `/home/brook/src/json-c'
make: *** [check-am] Error 2
brook@vista:~/src/json-c$ sed -i 's/-Werror //' Makefile
brook@vista:~/src/json-c$ make check
make  test1 test2 test4 test_parse_int64 test_null test_cast
make[1]: Entering directory `/home/brook/src/json-c'
...
brook@vista:~/src/json-c$ ./test1
my_string= 
my_string.to_string()="\t"
my_string=\
my_string.to_string()="\\"
my_string=foo
my_string.to_string()="foo"
my_int=9
my_int.to_string()=9
my_array=
 [0]=1
 [1]=2
 [2]=3
 [3]=null
 [4]=5
...


Parser
可以利用json_tokener_parse()直接將字串轉成json_object,或是利用json_object_from_file()直接將檔案轉成json_object。
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>

#include "json.h"


int main(int argc, char **argv)
{
  json_object *new_obj;

  MC_SET_DEBUG(1);

  new_obj = json_tokener_parse("/* more difficult test case */ { \"glossary\": { \"title\": \"example glossary\", \"GlossDiv\": { \"title\": \"S\", \"GlossList\": [ { \"ID\": \"SGML\", \"SortAs\": \"SGML\", \"GlossTerm\": \"Standard Generalized Markup Language\", \"Acronym\": \"SGML\", \"Abbrev\": \"ISO 8879:1986\", \"GlossDef\": \"A meta-markup language, used to create markup languages such as DocBook.\", \"GlossSeeAlso\": [\"GML\", \"XML\", \"markup\"] } ] } } }");
  printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
  json_object_put(new_obj);

  return 0;
}


Generator基本上就是用json_object_to_json_string()將json_object轉成字串。

更多的範例可以參考source code裡面的test1.c。



熱門文章