November 19, 2014

Read godoc in vim using Shift K

Add the following to your ~/.vim/ftplugin/go.vim (the key here is to use <cfile> not <cword>)

fun! ReadMan()
  " Assign current file under cursor to a script variable:
  let s:man_word = expand('<cfile>')
  :exe ":Godoc " . s:man_word
endfun
" Map the K key to the ReadMan function:
map K :call ReadMan()<CR>

=======UPDATE========
Had a better way for this:

1. Create a file in your ~/bin called godoc.sh with the following content:
#!/bin/sh
fullpkg=`gawk -v "cmd=$1" '
{ FS="/" }
{
        if ($NF==cmd || $0 ==cmd){
                printf("%s",$0);
                exit;
        }
}' ~/bin/gopkg-list.txt`
echo -n $fullpkg

2. Create a text file in ~/bin/gopkg-list.txt with the following contents:
log/syslog
unicode/utf8
unicode/utf16
testing
hash/crc64
hash/adler32
hash/fnv
hash/crc32
archive/zip
archive/tar
expvar
mime
reflect
crypto/des
crypto/sha1
crypto/subtle
crypto/aes
crypto/md5
crypto/cipher
crypto/rand
crypto/ecdsa
crypto/tls
crypto/sha512
crypto/x509
crypto/sha256
crypto/elliptic
crypto/hmac
crypto/rsa
crypto/x509/pkix
crypto/rc4
crypto/dsa
flag
strings
sync
os/user
os/signal
os/exec
os
fmt
syscall
time
runtime/pprof
runtime/cgo
runtime/debug
runtime/race
net/http/httputil
net/http/cookiejar
net/http/fcgi
net/http/pprof
net/http/cgi
net/http/httptest
net/rpc/jsonrpc
net/mail
net/http
net/textproto
net/url
net/rpc
net/smtp
io/ioutil
math
database/sql/driver
database/sql
mime/multipart
bytes
errors
sort
bufio
encoding
log
path/filepath
index/suffixarray
net
crypto
sync/atomic
go/printer
go/doc
go/scanner
go/ast
go/parser
go/token
go/build
go/format
unicode
image
io
runtime
html/template
regexp
html
container/ring
container/list
container/heap
hash
path
regexp/syntax
text/template/parse
text/tabwriter
text/template
text/scanner
strconv
testing/quick
testing/iotest
compress/flate
compress/zlib
compress/lzw
compress/bzip2
compress/gzip
image/color
image/draw
image/color/palette
image/png
image/gif
image/jpeg
encoding/base64
encoding/base32
encoding/xml
encoding/asn1
encoding/pem
encoding/ascii85
encoding/csv
encoding/hex
encoding/json
encoding/binary
encoding/gob
debug/pe
debug/plan9obj
debug/dwarf
debug/elf
debug/gosym
debug/macho
math/rand
math/big
math/cmplx

3. In your ~/.vim/ftplugin/go.vim, add the following:
fun! ReadMan()
  " Assign current file under cursor to a script variable:
  let s:man_word = expand('<cword>')
  let s:full_word = system('~/bin/godoc.sh '. s:man_word)
  :exe ":Godoc " . s:full_word
endfun
" Map the K key to the ReadMan function:
map K :call ReadMan()<CR>

This will take the keyword under cursor, expanded using the shell script, and call :Godoc on it. This takes care of subpackages

November 14, 2014

ios validate self signed certificate

http://stackoverflow.com/questions/10979922/ios-and-ssl-unable-to-validate-self-signed-server-certificate

Quote:


I did figure out how to resolve this issue.
I ended up comparing the client and server trust certificates, byte-by-byte. Although there could be another way to resolve such issues of self-signed certificate, but for this solution did work. Here is how I'm doing comparison of the client and server certificates, byte-by-byte, using their CFData objects(you can also reference 'AdvancedURLConnections' example code provided by Apple):
success = NO;
        pServerCert = SecTrustGetLeafCertificate(trust);
        if (clientCert != NULL) {
            CFDataRef       clientCertData;
            CFDataRef       serverCertData;

            clientCertData = SecCertificateCopyData(clientCert);
            serverCertData   = SecCertificateCopyData(pServerCert);

            assert(clientCertData != NULL);
            assert(serverCertData   != NULL);

            success = CFEqual(clientCertData, serverCertData);

            CFRelease(clientCertData);
            CFRelease(serverCertData);
        }
        if (success) {
            [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
            [self printLogToConsole:@"Success! Trust validation successful."];
        } else {
            [self printLogToConsole:@"Failed! Trust evaluation failed for service root certificate.\n"];
            [[challenge sender] cancelAuthenticationChallenge:challenge];
        }
Hope this will help someone, who is looking for solution of similar issue,

November 12, 2014

the ffmpeg command to explode video into still images

ffmpeg.exe -i IMG_0278.MOV -ss 0  -t 1 -f image2 -sameq -vcodec mjpeg "img-%03d.jpg"

-ss: start time, 0 means starting at 0 second mark
-t : number of seconds to explode


November 6, 2014

vim and error list

If you have text file that contains the list of errors with line positions, you can tell vim to use that to help you navigate through the list.

1. Edit the list to the following format (suppose it is named "errors.txt")
    xxxx.c:123: Warning/Error/Info rest-of-the-text
    where
    xxxx.c is the source code file name
    123 is the line number

2. vim -q errors.txt

3. now you can type ":cw" to open the "quickfix" window which list the errors, and use ":cn" and ":cp" to go through them. Mapping these to a short cut key will make life easier. I map mine to Ctrl-j and Ctrl-k for down and up (copy and the paste the following to your ~/.vimrc file)

    map <C-J> :cn<CR>
    map <C-K> :cp<CR>

November 5, 2014

check ip address owner

For an U.S IP address, you can go to the following site:

http://whois.arin.net

and put the IP address in the search box of top right corner, and you can get more info on it.

Once you find the owner, you can click on "Related Networks" to find all the IP addresses that owner owns.

November 3, 2014

How to dump Mac OS X dns cache

DNS cache information is not managed by Directory Services, contrary to popular opinion on this site. It's managed by mDNSResponder, and the man page contains the answer to your question:


A SIGINFO signal will dump a snapshot summary of the internal state to /var/log/system.log:

   % sudo killall -INFO mDNSResponder

October 31, 2014

Windows Active Directory (AD) LDAP binding account

The common way to bind to AD as an LDAP server is to use "Distinguished Name(DN)" and Password. The DN usually is in the form of:  CN=username,CN=Users,DC=yourdomain,DC=com

To find out DN, you can use Sysinternal's Active Directory Explorer to connect to AD and browse to the user to find out.

According to this post on stackoverflow, http://serverfault.com/questions/497368/ldap-activedirectory-binddn-syntax, you can also use UPN, which typically has the value of:

<sAMAccountName>@<domain FQDN>


Linux Frame buffer screen capture

1. Calculate the screen size. For example 1920 x 1080. Make sure that the width is a multiple of 4. For example, for HD screen resolution of 1366x768,  use 1368x768

2. dd if=/dev/fb1 bs=1368 count=3072 | gzip -c > screen.bgra.gz
   Each pixel is 4 byte, B-G-R-A. So 1368x768 resolution takes 1368*768*4=1368*3072 bytes

3. transfer the file to a Linux computer with imagemagick installed (needs a version released after 2010), and then convert it:
   gunzip screen.bgra.gz
   convert -size 1368x768 -depth 8 screen.bgra screen.png

Kerberos simplified

The 6 steps of Kerberos

Players:
  User
  Service (Can be any service that user wants to access, such as mail service)
  Kerberos Authentication Service (AS)
  Kerberos Ticket Granting Service (TGS)
  

                                      +--------------------+----------------------+
                                      |                    |                      |
                                      |     Kerberos AS    |     Kerberos TGS     |
                                      |                    |                      |
                                      +---------+----------+--------+-------------+
                                         ^      |              ^    |
                                         |      |              |    |
                                       1 |      |2           3 |    | 4
                                         |      |              |    |
                                         |      |              |    |
      +-------------------+              |      |              |    |                       +-----------------------+
      |                   |--------------+      |              |    |                       |                       |
      |                   |<--------------------+              |    |                       |                       |
      |                   +------------------------------------+    |                       |                       |
      |      User         |<----------------------------------------+         5             |     Mail Service      |
      |                   +---------------------------------------------------------------->|                       |
      |                   |<----------------------------------------------------------------+                       |
      +-------------------+                                                   6             +-----------------------+



Step 1: User          ---- Username, Timestamp                                               ----> Kerberos AS
Step 2: Kerberos AS   ---- TGT=[K(user,tgs)<-P(tgs)], K(user,tgs)<-P(user)                   ----> User
Step 3: User          ---- TGT<-P(tgs), user_name, service_name, authenticator<-K(user,tgs)  ----> Kerberos TGS
Step 4: Kerberos TGS  ---- ST=[K(user,service)<-P(service)], K(user,service)<-K(user,tgs)    ----> User
Step 5: User          ---- ST<-P(service), user_name, authenticator<-K(user,service)         ----> Service
Step 6: Service       ---- OK, authenticator<-K(user,service)                                ----> User


Authenticator = (sender_name, sender_address, timestamp, lifespan) <- SessionKey

K(user,tgs) : a session key, randomly generaged by Kerberos, shared betwee user and TGS
P(tgs)      : a key based on the password of the tgs service. It's a password known only by the tgs service
P(user)     : a key based on the password of the user
K(user,tgs)<-P(user) : meaning that K(user,tgs) is encrypted with the key of P(user)
TGT         : Ticket Granting Ticket. It's just a token that needed for the user to talk to TGS. It contains
              a session key known only by user and TGS.

Keytab files
In kerberos step 1, users can enter password to obtain the TGT from Kerberos TGS, what about services/devices? Kerberos allow the value P(user) to be exported and saved to a file, usually named keytab. This allows the service to authenticate users without talking to Kerberos server.

A really helpful story telling about Kerberos the authentication mechanism

http://web.mit.edu/kerberos/dialogue.html

I have read quite a few articles about Kerberos. Among them the above dialog is the most helpful. It does not hurt that it came from the original authors who help designed Kerberos.

October 17, 2014

Windows Server LDAP MaxPwdAge, MinPwdAge

When using AD Explorer software to query Windows Server, on a particular domain, you can see the maximum and minimum days required for password to change. These values show up as HEX values such as:

Max: 0xFFFFDEFF0AA68000
Min: 0xFFFFFF36D5964000

This is how to convert them to actual days:

( 0xFFFFFF36D5964000 - <64-bit value> ) / 0xC92A69C000 + 1 = answer ( in days)

Basically, the time unit here is 100ns (See http://en.wikipedia.org/wiki/System_time to see how Windows use 100ns as their system time unit). So
   1 day is 24*3600*10,000,000 = 864000000000 = 0xC92A69C000

Starting from an unsigned 64-bit 0 value,
1 day = 0 - 0xC92A69C000 = 0xFFFFFF36D5964000
2 day2 = 0xFFFFFF36D5964000   - 0xC92A69C000  = 0xFFFFFE6DAB2C8000
3 days = 0xFFFFFDA480C2C000
...
41 days = 0xFFFFDFC835104000
42 days = 0xFFFFDEFF0AA68000
43 days = 0xFFFFDE35E03CC000
44 days = 0xFFFFDD6CB5D30000
...
89 days = 0xFFFFBA10413C4000
90 days = 0xFFFFB94716D28000

So for the above example:

Max: 42 days
Min: 1 day

October 16, 2014

If you have a computer that joins to a domain, you can use LDAP to bind to the domain name controller and find a lot of information. Here is how you do it:

1. open a "cmd" window, and do: echo %logonserver% . This tells you the domain controller's name
2. download sysinternals AD explorer software, and connect to the domain controller
3. On the left tree, suppose your company's domain is abc.com, click on "DC=abc,DC=com"
4. In the subtree, click on "OU=...", and keep click on "OU=..." in the subtrees, until your find all the users with "CN=...". There you can see all the users of the domain, and all other information.

September 11, 2014

SNMP v3 trap and engineID

When sending an SNMP v3 trap from the sender to the trap receiver, the authoritative engineID is the trap sender's engine ID.   Below is a method to remotely discover the engine ID of  the remote SNMP sender (likely SNMP agent):

use the net-snmp snmpwalk command, and add the command option: "-Dsnmp_sess_open" and do a snmpget v3 with your credentials, and you should get something like this:

snmp_sess_open:   probe found engineID:  80001f888016fb784553d902ac
.1.3.6.1.4.1.3432.8.1.1.7.0 = Gauge32: 0

The agent's engineID is right there: 80001f888016fb784553d902ac

You can also try "-Dlcd_get_enginetime", which gives you local engineID

On the other note, I have written the SNMP trap receiver that can detect the incoming engineID automatically. Check it out at github: https://github.com/tiebingzhang/WapSNMP

On a local Linux machine running snmpd, you can find out its engine ID by:

cat /var/net-snmp/snmpd.conf

If you have any SNMP v3 user configured, you should see one or more lines like this:

usmUser 1 3 0x80001f888016fb784553d902ac 0x68636d2e736e6d70763300 0x......

EngineID is the 4th element: 0x80001f888016fb784553d902ac 



September 10, 2014

On a Linux box find out actual serial port being used

1. 
cat /proc/tty/driver/serial

and 

cat /proc/tty/driver/usbserial


2. dmesg | grep tty

3. setserial -g /dev/tty*


September 5, 2014

cross compile wpa_supplicant for arm

cd wpa_supplicant

edit the .config file, copy from a default one if you don't have one.

At the beginning of .config file, add:

CFLAGS += -I/opt/ezsdk/linux-devkit/arm-none-linux-gnueabi/usr/include -O2 -I../libnl/include -D_GNU_SOURCE
LIBS += -L/opt/ezsdk/linux-devkit/arm-none-linux-gnueabi/usr/lib/ -L../libnl/lib
CC=arm-none-linux-gnueabi-gcc


Then make

Use "make V=1" to get verbose out.

September 4, 2014

cross compile nginx for ARM

nginx is a nice web server for embedded systems, but it is frustrating to cross compile because it does not use the standard autoconf structure, and the author provides no documentation to help make this process easier.

This is just my way of cross compiling it, feel fee to comment on your way.

1. compile it for your host. In my case, that's x86_64 Linux. I do the following:

  ./configure --without-pcre --without-http_rewrite_module
  make

2. Now, hand tweak the generated Makefie

   vi objs/Makefile

replace the top few lines with the following (change it to your environment):

TOP := $(dir $(lastword $(MAKEFILE_LIST)))
CC =    arm-none-linux-gnueabi-gcc
CFLAGS =  -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Wunused-function -Wunused-variable -Wunused-value
CFLAGS += -I${TOP}/../openssl-1.0.1i/openssl-1.0.1i/include  -I/opt/ezsdk/linux-devkit/arm-none-linux-gnueabi/usr/include
LINK =  $(CC) -L${TOP}/../openssl-1.0.1i/

3. You may need to change the file objs/ngx_auto_config.h because some functions available on host are not available on your target. In my case, I had to remove lines containing ACCEPT4

4. clean the old obj files:
   find . -name "*.o" | xargs rm -f

5. make. The final binary is located objs/nginx

Note: make clean will remove the objs/Makefile you just changed. Make sure you have a backup.

cross compile openssl 1.0.1i for ARM

export CROSS_COMPILE=arm-none-linux-gnueabi-
export ARCH=arm
./Configure shared linux-armv4
CC=${CROSS_COMPILE}gcc RANLIB=${CROSS_COMPILE}ranlib make

August 29, 2014

GO SNMP implementation

This is a open source SNMP trap receiver written in GO:

https://github.com/tiebingzhang/WapSNMP

It supports SNMP v2c and V3 traps.

It also includes utilities to perform SNMP Get and SNMP walk for both SNMP v2c and V3.

Since it is written in GO, it compiles on both Linux and Windows (and in theory also Mac OS, but not tested).

my .gitconfig

[user]
        name = Tiebing Zhang
        email = tzhang@advistatech.com
[core]
        editor = vim
[merge]
        tool = vimdiff
[alias]
        d = difftool
        st = status -s
        ci = commit -a
        br = branch
        co = checkout
        df = diff
        dc = diff --cached
        last = log -1 HEAD --stat
        lg = log --stat
        who = shortlog -s --
[diff]
        renames = copy
        tool = gvimdiff
[difftool "gvimdiff"]
        cmd = "gvim -d" "$LOCAL" "$REMOTE"
[difftool]
        prompt = false
[push]
        default = matching
[sendpack]
        sideband = false

GO cross compile Windows binary on Linux


# set up cross compilation to windows_amd64
# you only need to do this once
cd $GOROOT/src
GOOS=windows GOARCH=amd64 ./make.bash --no-clean

# whenever you want to cross compile
cd $YOUR_APP
GOOS=windows GOARCH=amd64 go build

More at
https://inconshreveable.com/04-30-2014/cross-compiling-golang-programs-with-native-libraries/

August 12, 2014

netcat send file with progress indicator

The following C code compiles to a file nc-send-file, and it will send a file to a raw tcp socket (such as netcat with the command: nc -l -p 8000 > myfile ), with progress indicator for every 64K bytes sent. On Windows, compile it using MinGW the following Makefile:
nc-send-file:nc-send-file.c
        gcc -Wall -O2 -o $@ $^ -s -lws2_32
clean:
        rm -f nc-send-file.exe
C code:
#ifdef WIN32
#include "winsock2.h"
#else
#include "sys/socket.h"
#include "netinet/in.h"
#include "unistd.h"
#endif
#include "stdio.h"

int main(int argc, char**argv)
{
   FILE * fd;
   int sockfd,ret,n;
   struct sockaddr_in servaddr;
   char sendline[1024*64];
   unsigned int totalbytes=0;

   if (argc != 4)
   {
      printf("usage:  client [IP address] [PORT] [File]\n");
      exit(1);
   }
#ifdef WIN32
   WSADATA wsaData;
   if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0){
    fprintf(stderr, "WSAStartup() failed");
    exit(1);
   }
#endif

   sockfd=socket(AF_INET,SOCK_STREAM,0);

   memset(&servaddr,0,sizeof(servaddr));
   servaddr.sin_family = AF_INET;
   servaddr.sin_addr.s_addr=inet_addr(argv[1]);
   servaddr.sin_port=htons(atoi(argv[2]));

   if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))<0){
    fprintf(stderr,"Error connecting to target.\n");
    return -1;
   }

   fd=fopen(argv[3],"rb");
   if (fd==NULL){
    fprintf(stderr,"Opening file %s error\n",argv[3]);
    return -1;
   }

   while (1){
   ret=fread(sendline, 1, sizeof(sendline),fd);
   if (ret==0){
    if (feof(fd)){
     printf("Finished. Total bytes sent:%u\n",totalbytes);
    }else{
     printf("Error.\n");
    }
    break;
   }
      n=send(sockfd,sendline,ret,0);
   if (n!=ret){
    printf("did not send all in the buffer. expecting %d sent %d exit.\n", ret, n);
    return -1;
   }
   totalbytes+=ret;
   printf("sending %d bytes, total %d bytes\n",ret, totalbytes);
   }
   fclose(fd);
#ifdef WIN32
   closesocket(sockfd);
   WSACleanup();  /* Cleanup Winsock */
#else
   close(sockfd);
#endif
   return 0;
}

August 8, 2014

xrdp reconnect to the same session

cat xrdp/xrdp.ini

[globals]
bitmap_cache=yes
bitmap_compression=yes
port=3389
crypt_level=high
channel_code=1

[xrdp1]
name=sesman-Xvnc
lib=libvnc.so
username=ask
password=ask
ip=127.0.0.1
port=-1

[xrdp2]
name=Reconnect
lib=libvnc.so
username=ask
password=ask
ip=127.0.0.1
#port=-1
port=5910


Use stunnel to access https

stunnel -c -d localhost:8000 -r foo:443 -P /tmp/stunnel.pid -f

Now you can access local 8000 using plaintext so that you can debug and sniff packets.

July 6, 2014

ipsec local routing bypass

Suppose that you have a ipsec site-to-site network as follows:

On local: from 10.1.0.0/16 to 0.0.0.0/0  goes to remote ipsec
On remote: from 0.0.0.0/0 to 10.1.0.0/16 goes to ipsec

Now on local you have a subnet 10.1.1.0/24 that you want to talk to. For example, you local interface eth1 has 10.1.1.1, and there is another computer on your network 10.1.1.2. Now if you want to ping 10.1.1.2 it would not work, because the traffic is captured by the ipsec policy (use "ip xfrm policy" to show it) and directed to ipsec tunnel.

To add local route bypass, use this:
ip xfrm policy add dir in src 10.1.1.0/24 dst 10.1.1.0/24
ip xfrm policy add dir out src 10.1.1.0/24 dst 10.1.1.0/24

run this after your ipsec tunnel is up. Then you should be able to ping 10.1.1.2.

Note when I add polices directly use "setkey" it did not work for me.

Looks like StrongSwan can do this using config file section called "shunt" policies. Needs to try this.

July 3, 2014

sfdisk tips

sfdisk can be used to list partition information and alter partition tables

cat /proc/partitions to see the list of kernel recognized drivers and partitions

sfdisk -l : list information

sfdisk -l -u M : list information using MiB as unit. 

sfdisk -l -u S : List information using sector (512 bytes) as unit.

Example:
 sudo sfdisk -l /dev/sdc -u M

Disk /dev/sdc: 1044 cylinders, 255 heads, 63 sectors/track
Warning: extended partition does not start at a cylinder boundary.
DOS and Linux will interpret the contents differently.
Units = mebibytes of 1048576 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start   End    MiB    #blocks   Id  System
/dev/sdc1   *     1   7806   7806    7993344   83  Linux
/dev/sdc2      7807+  8190    384-    392193    5  Extended
/dev/sdc3         0      -      0          0    0  Empty
/dev/sdc4         0      -      0          0    0  Empty
/dev/sdc5      7808   8190    383     392192   82  Linux swap / Solaris

Notice "7807+" and "384-" means that the numbers are not a multiple of MiB. Therefore that partition is not MiB aligned. For Extended partition, that is OK, but for real data-holding partitions, you may want them to be MiB aligned.

This is the list by sector results:
sudo sfdisk -l /dev/sdc -u S

Disk /dev/sdc: 1044 cylinders, 255 heads, 63 sectors/track
Warning: extended partition does not start at a cylinder boundary.
DOS and Linux will interpret the contents differently.
Units = sectors of 512 bytes, counting from 0

   Device Boot    Start       End   #sectors  Id  System
/dev/sdc1   *      2048  15988735   15986688  83  Linux
/dev/sdc2      15990782  16775167     784386   5  Extended
/dev/sdc3             0         -          0   0  Empty
/dev/sdc4             0         -          0   0  Empty
/dev/sdc5      15990784  16775167     784384  82  Linux swap / Solaris

Notice now there is no +/- anymore, and start/end are in sectors. This will give you exact layout of the partitions.

Write partitions:
sfdisk takes two kinds of formats as input to write partitions: the "manual" format as documented in the man page, and the "dump" format.

Use "-d" to dump the current partition table.

 sudo sfdisk -d /dev/sdc
# partition table of /dev/sdc
unit: sectors

/dev/sdc1 : start=     2048, size= 15986688, Id=83, bootable
/dev/sdc2 : start= 15990782, size=   784386, Id= 5
/dev/sdc3 : start=        0, size=        0, Id= 0
/dev/sdc4 : start=        0, size=        0, Id= 0
/dev/sdc5 : start= 15990784, size=   784384, Id=82

Now you can edit this file, and then feed it back to change partitions using command "sfdisk -d /dev/sdc < part.txt", supposing that you wrote the above text to "part.txt" file.

Now some explanation of the "dump" format:

1. Empty lines are ignored
2. # and things after it is ignored (for that line)
3. "unit: sectors" is recognized as a valid command to set unit to sectors
4. Each partition line starts with the partition name, which is ignored. Then ":", then  multiplle "variable-name=value" separated by ",". "bootable" is special because it is a boolean value.
5. All values have to be present. No auto calculation as in "manual" mode.

Partition Alignment
When I tried to start partitioning on the 2nd cylinder instead of the first,  I ran into issues. The command was:

sfdisk /dev/sdb -H 16 -S 63 <<EOF
1,159,83
,4096,82
,,83
;

EOF

My 80GB disk does not have a multiple of 2048 sectors, because the total number of sectors is a multiple of 63, which is the typical sectors per track. So to make my partition aligned at least to 4K, I used head of 16, which gives me the cylinder size of 63*16*512bytes=63*8KiB, so my cylinder is 4KiB aligned.

The above command will produce the following error:
sfdisk: Warning: given size (4096) exceeds max allowable size (1)
sfdisk: bad input

I was very puzzled. After compiling sfdisk from source code and adding debug statements in it, I finally found out the reason: sfdisk is trying to fit the 2nd partition in the first free cylinder because it think it is free! Well it is free except for the MBR in the first sector, but I don't want my 2nd partition to there. How do we tell sfdisk that? Here comes the "undocumented dangerous option" "--in-order". If you specify the "--in-order", sfdisk will work as you intended it to.

OR, you could manually specify the start address of each partition.

So the final working command is:
sfdisk /dev/sdb --in-order -H 16 -S 63 <<EOF
1,159,83
,4096,82
,,83
;
EOF


At last, you can use "hdparm -i" to list harddrive info, including number of LBA sectors. However, this may not work on some disks. 

July 2, 2014

Understand fdisk output


Disk /dev/hdb: 64 heads, 63 sectors, 621 cylinders
Units = cylinders of 4032 * 512 bytes
 
   Device Boot    Start       End    Blocks   Id  System
/dev/hdb1   *         1       184    370912+  83  Linux
/dev/hdb2           185       368    370944   83  Linux
/dev/hdb3           369       552    370944   83  Linux
/dev/hdb4           553       621    139104   82  Linux swap

Sector size: 512 bytes

64 Heads: there are 64/2=32 platters in the disk, each platter has 2 heads. Think head as a surface.

63 sectors: Each head is divided in to 63 sectors

621 cylinders: There are 621 of concentric tracks/cylinders on each head. Each track has 63 sectors as indicated above. 

A cylinder is a vertical slice of a track on all heads. Cylinder size = #Heads * #sectors * 512 = 64*63*512 = 4032*512 = 2064384 bytes

Disk are allocated from low cylinders to high cylinders. 

Start/End unit is cylinder. 

Block size is 1024 bytes. 

Blocks per cylinder is 2064384/1024 = 2016

The "+" sign in "370912+" means the number 3780912 is not accurate. The actual blocks should be a little more. To calculate the actual one, just do 370912/2016=183.98, and then rounded it up to get 184. So the first partition has 184 cylinders.

Another example:
Disk /dev/sda: 250.0 GB, 250059350016 bytes
64 heads, 32 sectors/track, 238475 cylinders
Units = cylinders of 2048 * 512 = 1048576 bytes
   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1          81   82928   83  Linux
/dev/sda2              82        2082   2049024    83  Linux
/dev/sda3            2083      238475   242066432   83  Linux

Cylinder size = 64*32*512=1048576 (1MB)
Blocks per cylinder = 1MB/1024=1024


July 1, 2014

Linux USB sysfs device naming scheme

In Linux dmesg, you may see something like this:

usb 1-1.1: new high speed USB device using musb-hdrc and address 8
usb 1-1.1: New USB device found, idVendor=05e3, idProduct=0608
usb 1-1.1: New USB device strings: Mfr=0, Product=1, SerialNumber=0
usb 1-1.1: Product: USB2.0 Hub
hub 1-1.1:1.0: USB hub found

The naming scheme is like this:

root_hub-hub_port.hub_port.hub_port(...):config.interface

So 1-1.1:1.0 means:

Device connected to Root Hub 1, Port 1 which has another hub connected to it, Port1. Then Config 1, and interface 0.

June 30, 2014

php md5sum

#!/usr/bin/php -f
<?php
if (count($argv)<2) die("no file specified\n");

if (!file_exists($argv[1])) die ("file does not exist\n");
echo md5_file($argv[1])."\n";

June 25, 2014

git windows push hang 100%

Solution:

1. Download the latest git for windows http://git-scm.com/download/win
2. git config --global sendpack.sideband false

You can also hack the git binary (either on Server or on Client) to change the string "side-band-64k" to something different such as "side-bond-64k". This essentially disables git side-band.

http://billauer.co.il/blog/2012/10/git-pull-windows-freeze-receive-pack/

install gitweb on ubuntu/debian


you have to install the package gitweb sudo apt-get install gitweb

Then you have to edit the apache gitweb config file
$EDITOR /etc/apache2/conf.d/gitweb
change the line Alias /gitweb /usr/share/gitweb to Alias /git /usr/share/gitweb

open the /etc/gitweb.conf file:
you have to change the line $projectroot ".." to $projectroot "/code/git"
and change any other line containing /gitweb to /git for example
$stylesheet = "/gitweb/gitweb.css";
to $stylesheet = "/git/gitweb.css";


then reload you apache webserver with sudo /etc/init.d/apache2 force-reload


[Source:http://askubuntu.com/questions/10452/setting-up-gitweb-apache2]

June 13, 2014

Kernel bypassing networking

Here is a selection of the many kernel-bypass solutions that are available:
These products each take their own design approaches and it’s interesting to consider choices that they make.

  • Customized kernel device driver. netmap and DNA both fork standard Intel drivers with extensions to map I/O memory into userspace.
  • Custom hardware. Myricom and Napatech both distribute bespoke device drivers for their own custom hardware (ASIC for Myricom and FPGA for Napatech).
  • Userspace library. These solutions each provide unique libraries to access their extensions. The scope varies tremendously: Ethernet I/O, libpcap compatibility, hardware-assisted traffic dispatching for multiprocessing, buffer memory management, all the way up to entire TCP/IP socket layers.
  • Licensing. netmap is open-source, DNA requires a modest license for its userspace library, Napatech requires an NDA and depends on very expensive hardware.

June 11, 2014

golang http client Server Sent Event receiver

package main

import (
 "crypto/tls"
 "log"
 "bufio"
 "net/http"
 "time"
)

func main() {
 var client *http.Client
 tr := &http.Transport{
  TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
 }

 client = &http.Client{tr, nil, nil, 0 * time.Second}

 /* open a request, can't use httpclient.Get because we need the http.Request so we can close the connection later */
 req, err := http.NewRequest("GET", "https://dev1.advistatech.com/sse2.php", nil)
 if err != nil {
  log.Fatal(err);
 }

 resp, err := client.Do(req)
 if err != nil {
  log.Fatal(err);
 }
 log.Printf("connected\n");

 reader:=bufio.NewReader(resp.Body);
 for {
  line,err:=reader.ReadString('\n');
  if err != nil {
   log.Fatal(err);
  }else{
   log.Printf("resp:%s\n",line);
  }
 }

 //respbytes, _ := ioutil.ReadAll(resp.Body)
 //log.Printf("resp: %s\n", respbytes)

 resp.Body.Close()
}

June 10, 2014

California FTB live person

Service section at 800.852.5711.
The hours of operation are 7:00 a.m. - 5:00 p.m., Monday through Friday, except state holidays.
Choose the Business prompt 2 to then 4 to speak to a live representative.  

Openssl AES-NI Test

For OpenSSL versions after 1.0.1, AES-NI should be buit-in. This is how to test it:

Command A (with AES-NI) = openssl speed -elapsed -evp aes-128-cbc
Command B (Without AES-NI) = OPENSSL_ia32cap="~0x200000200000000" openssl speed -elapsed -evp aes-128-cbc

bit #33 denoting availability of PCLMULQDQ instruction (for AES-GCM computation);
bit #57 denoting AES-NI instruction set extension;

Results:
Command   16 bytes     64 bytes     256 bytes    1024 bytes   8192 bytes
------------------------------------------------------------------------
A         796435.32k   845155.61k   852750.59k   860752.55k   865828.86k
B         393740.06k   431465.71k   438168.23k   443452.42k   446458.54k

http://www.openssl.org/docs/crypto/OPENSSL_ia32cap.html

June 4, 2014

How to add a schema to OpenLDAP server

vim /tmp/borrame.conf
(this is what goes in the file)

include /etc/ldap/schema/core.schema
include /etc/ldap/schema/cosine.schema
include /etc/ldap/schema/nis.schema
include /etc/ldap/schema/inetorgperson.schema
include /etc/ldap/schema/misc.schema
include /etc/ldap/schema/mypersonalschema.schema

mkdir /tmp/borrame.d
slaptest -f /tmp/borrame.conf -F /tmp/borrame.d

Edit the generated file
vim /tmp/borrame.d/cn\=config/cn\=schema/cn\=\{5\}mypersonalschema.ldif

I changed the three head lines to this:
dn: cn=mypersonalschema,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: mypersonalschema

Then I deleted these lines from the bottom of the file:

structuralObjectClass:
entryUUID:
creatorsName:
createTimestamp:
entryCSN:
modifiersName:
modifyTimestamp:

And at last I inserted the new schema to the ldap tree:
ldapadd -Y EXTERNAL -H ldapi:/// -f /tmp/borrame.d/cn\=config/cn\=schema/cn\=\{5\}mypersonalschema.ldif

Add LDAP user authentication to YellowDog Linux

/etc/ldap.conf
*************************************
host ldap-server-ip-address
base ou=Users,dc=advistatech,dc=com
ssl no
pam_password md5
*************************************

/etc/openldap/ldap.conf
*************************************
HOST ldap-server-ip-address
BASE ou=Users,dc=advistatech,dc=com
*************************************

/etc/pam.d/system-auth
*************************************
auth required /lib/security/$ISA/pam_env.so
auth sufficient /lib/security/$ISA/pam_unix.so likeauth nullok
auth sufficient /lib/security/$ISA/pam_ldap.so use_first_pass
auth required /lib/security/$ISA/pam_deny.so

account sufficient /lib/security/$ISA/pam_succeed_if.so uid < 100
account required /lib/security/$ISA/pam_unix.so
account [default=bad success=ok user_unknown=ignore] /lib/security/$ISA/pam_ldap.so

password requisite /lib/security/$ISA/pam_cracklib.so retry=3
password sufficient /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow
password sufficient /lib/security/$ISA/pam_ldap.so use_authtok
password required /lib/security/$ISA/pam_deny.so

session required /lib/security/$ISA/pam_limits.so
session required /lib/security/$ISA/pam_unix.so
session optional /lib/security/$ISA/pam_ldap.so
*************************************

nsswitch.conf
**********************
passwd: files ldap
shadow: files ldap
group: files ldap
**********************

You can use "getent passwd" to  list all the users in the ldap server.

To make sshd work, restart the sshd service.

May 31, 2014

Newbie’s OpenLDAP tips

  1. Newbie’s OpenLDAP tips

    1. Following https://help.ubuntu.com/12.10/serverguide/openldap-server.html to get OpenLDAP server and tools installed and configured on your server.
    2. The binary is called slapd. The configuration file is not a file anymore, but a directory structure in LDAP file format. The files used in LDAP is using the LDIF format, which is plaintext. The configuration is stored at /etc/ldap/sldap.d/, in file “cn=config.ldif” and inside directory “cn=config”.
    3. The ldap server access credential is stored in  file “cn=config/olcDatabase={1}hdb.ldif”
      1. olcRootDN:
      2. olcRootPW:
    4. User LDAP data is stored in /var/lib/ldap using a binary DB format (Berkely DB or some other DB format). User LDAP data can only be viewed by using LDAP tools such as ldapsearch, and can be edited by ldapadd, ldapdelete, ldapmodify,etc
    5. Command to list all entries
      1. ldapsearch -x -LLL -b dc=advistatech,dc=com
    6. To authenticate to ldapserver when running command like ldapsearch, you can use “-x”, which is amount to local authentication. Or you can “bind” to the server using the credential listed above in “olcRootDN” and “olcRootPW” as follows. Only binding will print out user password information stored in LDAP DB.  See more at http://blogs.splunk.com/2009/07/30/ldapsearch-is-your-friend/
      1. -D "cn=admin,dc=advistatech,dc=com"
        -W will prompt you for your password
    7. PHP can act as a LDAP client. It has dedicated function to connect, bind, and query LDAP Servers.
    8. In PosixAccount object (like Unix user account), the password field name is “userPassword”. It is usually hashed with LDAP special seeded SHA1 hash function. If you query it when bound to the server, you will see something like {SSHA}….
    9. ldapcompare does not automatically hash clear password when comparing. So you would need to hash the password first (probably using ldappasswd) and then do the compare (to be validated)
    10. The usually way to testing an user’s account credential is actually try to bind (login) to the ldap server using that credential.
    11.  A simple PHP script to test a user credential:
    <?php
    $ds=ldap_connect("localhost");
    if (!$ds) {
        die ("Unable to connect to LDAP server.");
    }

    ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($ds, LDAP_OPT_REFERRALS, 0);

    $dn = "uid=tony,ou=Users,dc=advistatech,dc=com";
    $pass= "mypass";

    // bind
    if (ldap_bind($ds,$dn,$pass))
    {
        echo ("bound successfully");
    } else {
        echo "Unable to bind to LDAP server.";
    }

    ldap_close($ds);

May 30, 2014

ldapscript not working fixed

Make sure your /etc/ldapscripts/ldapscripts.passwd does not contain a trailing newline. (This is the default behaviour of many editors, including vim)

samba server symbolic links

To enable symbolic links, edit smb.conf with the following changes:

1. Add the following lines in the [global] section
[global]
    follow symlinks = yes
    wide links = yes
    unix extensions = no

2. Add the following lines to your shared directory section
[home]
    follow symlinks = yes
    wide links = yes

3. Restart smbd. On Fedora/Redhat, use  
         sudo systemctl restart smb.service
   on Debian/Ubuntu, use
        sudo /etc/init.d/smbd restart

May 2, 2014

The Secret to 10 Million Concurrent Connections -The Kernel is the Problem, Not the Solution

http://highscalability.com/blog/2013/5/13/the-secret-to-10-million-concurrent-connections-the-kernel-i.html

Netmap

Intel DPDK

PF_RING

April 22, 2014

ultravnc has better performance than tightvnc on Windows 7

Use ultravnc (Windows 7 X64) and you should see better performance.

Prolific USB to COM driver can not start error code 10 on Windows 7 64-bit

There are a couple of prolific chipsets i've seen, the older chips sets don't seem to work with the new driver on the prolific website.

Which version: Rev_0300 or Rev_0400
1. Plug in the adapter and open the device manager.
  • If the driver is loaded, you'll see the device under ports, probably with a Yellow !
  • If the driver isn't loaded it will likely appear under Other (or unknown?) Devices.
2. Double click the adapter to open its properties.  
3. Go to the details tab in the top right.
4. Click the drop down box and choose Harware IDs.
5. Note if it says Rev_0300 or Rev_0400

Which Driver Version
  • Rev_0400 works with the lasest drivers from the Prolific Website (Xp, Win7 32 or 64.) 
  • Rev_0300 needs older drivers XP: driver version 2.0.2.24.  Windows 7 (32 and 64) version 3.0.1.0.  Download it HERE or HERE
Loading the Drivers:

Win7

1. Run the application VISTA.EXE to install the drivers.  Open the device manager and the adapter should be present under Port and may be showing a yellow ! exclamation mark showing in the device manager and reporting Code 10.  (If it looks normal, it's already good to go)

2. Right click the device (in the device manager) and choose update driver. Don't let windows update automatically - you need to pick from a list. 

After clicking update drvier choose:

  • Browse My Computer for Drvier Sowftware
  • Let me pick from a list of device drivers on my computer
  • Prolific USB-to-Serial Comm Port version [version] > Next

April 8, 2014

build a golang cross-compile toolchain for ARM on Linux

1. Download the latest golang source: wget https://go.googlecode.com/files/go1.2.1.src.tar.gz
2. export GOOS=linux
3. export GOARCH=arm
4. export GOARM=7 (find out your ARM version based on the ARM processor). This step can be skipped as long as you know your ARM version is not 5.
5. export GOROOT=/home/me/go (set this to where your untarred go directory)
6. cd go/src; ./make.bash

There you have it.

April 1, 2014

Parsing URLs with the DOM!

http://james.padolsey.com/javascript/parsing-urls-with-the-dom/

parseURL

// This function creates a new anchor element and uses location
// properties (inherent) to get the desired URL data. Some String
// operations are used (to normalize results across browsers).
 
function parseURL(url) {
    var a =  document.createElement('a');
    a.href = url;
    return {
        source: url,
        protocol: a.protocol.replace(':',''),
        host: a.hostname,
        port: a.port,
        query: a.search,
        params: (function(){
            var ret = {},
                seg = a.search.replace(/^\?/,'').split('&'),
                len = seg.length, i = 0, s;
            for (;i<len;i++) {
                if (!seg[i]) { continue; }
                s = seg[i].split('=');
                ret[s[0]] = s[1];
            }
            return ret;
        })(),
        file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
        hash: a.hash.replace('#',''),
        path: a.pathname.replace(/^([^\/])/,'/$1'),
        relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
        segments: a.pathname.replace(/^\//,'').split('/')
    };
}

Usage

var myURL = parseURL('http://abc.com:8080/dir/index.html?id=255&m=hello#top');
 
myURL.file;     // = 'index.html'
myURL.hash;     // = 'top'
myURL.host;     // = 'abc.com'
myURL.query;    // = '?id=255&m=hello'
myURL.params;   // = Object = { id: 255, m: hello }
myURL.path;     // = '/dir/index.html'
myURL.segments; // = Array = ['dir', 'index.html']
myURL.port;     // = '8080'
myURL.protocol; // = 'http'
myURL.source;   // = 'http://abc.com:8080/dir/index.html?id=255&m=hello#top'
I’ve tested this solution in all modern browsers (including IE6) and it seems to work perfectly. If you spot any inconsistencies please let me know.

If you don’t feel comfortable using something which relies on the DOM then have a look at this although please note it’s about 12 times slower than the above solution…

March 23, 2014

《中华文明外来说的各种版本》


   “中国文化西来”的论调,明末清初西方传教士东来之时就已经开始了~~~~
  【1】 手捧《圣经》,一心想把“上帝”传给中国人的西方传教士,依据《圣经》中之创世纪、乐园放逐、洪水等记载,宣称中国文化起源于西方基督教,如清初由传教士 汤若望授意、钦天监监正李祖白撰成的《天学传概》中写道:“初人子孙聚处如德亚(指犹太)。……其后生齿日繁,散走遐逖。……在中国为伏羲氏,天学固其所 以怀来也。”
  
  【2】 随着欧洲殖民主义兴起,部分外国人的文化殖民心理也随之膨胀,不承认中国古代文明有自己独立的起源。
   发端于17世纪。德国耶稣会传教士基尔什尔(A.Kircher)在其著作《埃及之谜》(1654)与《中国图说》(1667)中首次提出,中国文明出于 埃及。他认为《圣经》所载闪的子孙率埃及人来到中国。把古埃及文字传授给中国人。此后持中国文明西来说者层出不穷,一个共同特点是否认中国文明的远古,不 相信远古的中国人会创造出辉煌的文明
  
  【3】 1716年,法国阿夫朗什主教胡爱(Huet)论证中国人乃埃及人之苗裔
  
  【4】 1758年法国汉学家约瑟夫·德·古尼著书立说认为,中国人乃是从埃及殖民过来的。
  
  【5】 同时期另外两位法国的汉学家波提(M.G.Pauthier)和卢内尔曼将汉字和楔形文字进行比较,提出了中国文明和巴比伦文明有亲缘关系的说法。
  
  【6】 十九世纪六七十年代英国传教士理雅各(JamesLegge)提出了诺亚的子孙东行来到了中国之说。
  
  【7】 十九世纪后期,德国著名的地理学家李希霍芬(“丝绸之路”这个词就是他发明的)也主张“中国人是西方移入”之说。
  
  【8】 1894年,法国人拉克佩里发表《中国古文明西源说》。他以19世纪欧洲考古界对近东地区的挖掘成果为基础,提出中国文明源于两河流域古巴比伦文明,汉族 是在公元前2200左右从西亚迁来的。并先后发表多部相关著作。拉克佩里“西来说”的根据是搜寻中国早期与古巴比伦的种种相似性。主要有天文历法方面,科 技发明方面,语言文字方面, 政治制度方面,历史传说方面,
   拉克佩里关于中国文明起源于古巴比伦的观点,显然是受到当时欧洲流行的文化传播学派的有关理论的影响。文化传播学派持世界文明的单一起源论,然后就变成了 “西源论”,即认为亚非拉等非西方地区的文明或多或少是受到西方早期文明“启示”和影响的结果,这显然是殖民主义者为其扩张侵略而进行的一种赤裸裸的辩 护。
  
  【9】 1900年,两位日本业余历史学者白河次郎和国府种德将拉克伯里的“西来说”写入面向一般大众的《支那文明史》一书中,认为中国文明起源于巴比伦,并列举了古代中华在学术、文字、政治、宗教等方面多达七十多处的相似。
  
  【10】 进入民国时代,拉克佩里“西来说”在国人中仍有相当的影响,如1915年浙江学者丁谦出版《中国人种从来考》,以《穆天子传》为主要资料,来考证中国民族 西来的有关史迹。至1918年还有人撰文指出:“朔轩辕东征之迹,其必由衡山钟山复逾昆仑,而后入于中夏,繁衍其子孙民族,以肇造此泱泱古大邦。”
  清末民初一批学者信从“西来说”,所依据的中国古文献,主要是《山海经》、《穆天子传》、《列子》、《路史》等著作。上述著作毕竟神话成分大大超过历史成分,其可信性值得推敲。不经过严谨的辨伪而盲信古书,穿凿附会,结果闹出很多笑话。
  
  【11】, 瑞典地质学家安特生考察了仰韶文化。1923年,安特生发表了《中华远古之文化》一文,把仰韶文化与中亚的安诺文化进行比较时,却得出了它们有可能同出一 源的结论,并且认为最先发现的安诺彩陶早于仰韶,所以仰韶文化有可能从西方经中亚传入。这就是著名的“中华文化西来说”。
  
  【12】 最近出现的“天马流星拳”, 苏三女士,居住在北京的人类学家,著有几部关于古代文明和人类学的玄幻作品。她认为,中国文化起源于中东,来到中国的红海沿岸的古埃及人或以色列人构成了 中国的夏、商、周文化,中国汉人主要是这些人的后裔。苏三的论证大部分都是从人名地名的音、义近似上所作的分析和猜测,并无过硬的物证。比如,
   "夏后朝"由亚伯拉罕后妃Hagar(夏甲)在大约4000年前建立
   "殷"由"红色"的以扫与其妻Judith(简狄)在大约3800年前建立
   "周"就是"Jew"(犹太人),其主要建立者为以色列12支系中的"但"家族
   黄帝可能是3700年前统治古埃及的约瑟,简狄应为其伯母。。。。。。

March 11, 2014

ARM U-boot Init sequence

This is how it goes:

arch/arm/cpu/arm_cortexa8/start.s (replace cortexa8 with your CPU)

- Interrupt vectors setup
-  cpu_init_crit
- u-boot relocate
- stack setup
- call C code start_armboot, located at arch/arm/lib/board.c

But start_armboot is not the first C function called.

cpu_init_crit -> calls lowlevel_init, which is located at  under your specific CPU, such as arm_cortexa8/ti81xx/lowlevel_init.S, then a function s_init (with label s_init_start) is called. This function is a C function located at boards/ti/ti8168/evm.c

So s_init is called way earlier than start_armboot in lib/board.c


March 3, 2014

libltdl in wrong place when cross compiling

When you cross compile a software, and your cross compiler is using /usr/lib/libltdl.so instead your cross compiler's libltdl, this is how to solve it:

export LIBTOOL_SYSROOT_PATH=/opt/ezsdk/linux-devkit/arm-none-linux-gnueabi/

Fix the path above to your cross compiler's libldtl directory.

The file libltdl.la ( a text file) in my build server uses the environment variable LIBTOOL_SYSROOT_PATH to find the libltdl.so file. So make sure that environment variable is defined, not only in configure time, but also before you run  Make.

中国人到底是诺亚哪个儿子的后裔

转载, 一家之言,仅供参考:

华人基督徒多半认为咱们“炎黄子孙”同犹太人一样,是挪亚(Noah)的儿子“闪”(Shem)的后裔,但是谁也找不到证明这一说法的圣经出处。一言以蔽 之,这种说法只是根据教会传统,并不是根据圣经。本人在这里全盘否定这一说法本意并不是要掀起一个“轩然大波”;而是要以圣经为依据来陈述并与大家分享一 个尘封已久的信息:“炎黄子孙”不是“闪”的后裔,而是“含”(Ham)的后裔;更准确地说,“炎黄子孙”正是那被诅咒的“迦南”(Canaan)的后 裔。《创世纪》十章里比较详尽地记述了从挪亚的三个儿子闪、含和雅弗(Japheth)开始的世界各民族雏形和发展去向。历代以来,所有依据本章圣经进行 的人类学及人种学方面的考古或研究都能从经节中获得特别的启示和正确的引导并且大大获益。


常常遇到一个常识性偏误,就是认为含的后裔是非洲人。根据《创世纪》十章六节,含生了古实(Cush)、麦西(Mizraim)、弗(Phut)和迦南 (Canaan)四个儿子。说非洲黑人是古实的后裔没有问题,然而请不要忽略:古埃及人和非利士人(Philistines,巴勒斯坦因此得名)也是麦西 的后裔(注:埃及和麦西在希伯来语里是一个词,以色列人现在仍然把埃及称为“Mizraim”而不称为“Egypt”。)。然而古埃及文明存留下来的仅有 金字塔等建筑和一些文物;与汉语同属象形文字的古埃及语也销声匿迹了;古埃及人千百年来也已被闪系的阿拉伯人融合或同化(似乎穆巴拉克等埃及人的脸部轮廓 尚留存了一丝麦西――含系的扁平特征,金字塔里的木乃伊也非常具有“含族”的特征---脸部,尤其是鼻子扁平)。另外,在两河流域的亚述建造尼尼微等城市 的宁录(Nimrod)也是古实的后裔,以色列人的苦敌耶布斯人(Jebusite)、亚摩利人(Amorite)等等都是迦南的后裔。

《创世纪》十章十五~十八节(和合本)是这样记载的:(15)迦南生长子西顿,又生赫,(16)和耶布斯人,亚摩利人,革迦撒人,(17)希未人,亚基人,西尼人,(18)亚瓦底人,洗玛利人,哈马人,后来迦南的诸族分散了。这里的十七节提到了迦南的一个儿子西尼(Sini),Sini竟然是现代以色列人用来对我们一切华人(含港澳台胞和海外侨胞)的称呼!我三年前偶然发现了这个问题。“后来迦南的诸族分散了”这句话很有意味,尽管没有给出分散的方向。有人说Sini是“西奈人”,但希伯来语保留下来的发音在“西奈”和“西/希尼”上的区别是明显的。

与此经节呼应,见于以赛亚书四十九章十二节(和合本):“…看哪,这些从远方来:这些从北方、从西方来,这些从秦国来(“秦”原音作“希尼”)。”“希尼”的希伯来原文是前面所提及的“西尼”的复数形式(“秦国”意即“西尼人的地方”)。

针对这两处圣经节,我趁今年一、二月份在耶路撒冷希伯来大学进修现代希伯来语之际,抱着原文(古希伯来语)圣经问过不下十个母语为希伯来语的以色列人,从法官到律师到教师到学生到医生到导游…所有人的回答都一样,他们直截了当地告诉我:这两个西尼(或希尼)指的就是你!就是你们中国人!!!“西尼”原文是单数Sini,指的是迦南的儿子;“希尼”原文是复数Sinim,是西尼人的复数形式。根据读音,西尼、希尼和细腻、悉尼、稀泥…实 质上根本没有什么不同!用字不同的原因完全是由于翻译问题造成的。另外,古希伯来语和现代希伯来语皆称中国为“Sin”(发音确像“秦”,碰巧跟英语“罪 性”---sin读音一样,不过是个专有名词),称中国男人为Sini,称这个女人为Sinit,(复数为Sinim),称汉语(华语)为 “Sinit”。

也许是因为挪亚关于迦南所说的预言让炎黄子孙在心理上难以承受;也许有人说炎黄子孙和犹太人有惊人的相似点…于是将炎黄子孙说成是“闪”的子孙就似乎没有人愿意去怀疑甚至否定了。谬误传多了传滥了传开了传久了也就很容易被当作真理来对待了。看看《创世纪》九章二十五~二十七节(和合本)是怎么说的:(25)(挪亚)就说,“迦南当受咒诅,必给他弟兄作奴仆的奴仆。(26)又说,耶和华闪的神是应当称颂的,愿迦南作闪的奴仆。(27)愿神使雅弗扩张,使他住在闪的帐棚里,又愿迦南作他的奴仆。”


你不相信炎黄子孙是被诅咒的民族吗?其实你可以翻一翻华夏历史看一看,再想一想:你真的觉得中华民族从古至今所受的诅咒还不够多不够惨吗?世界上还能有哪 个民族会像中华民族这样被“真龙天子”们折腾得伏屍遍野忍气吞声低三下四毫无脾气的?如果不愿承认“受诅咒”的事实,为何总是把“灾难深重”与“中华民 族”连在一起用呢?被雅弗后裔(英美法德等为代表)殖民的一百多年历史难道被遗忘了吗?就连那同属含系后裔的日寇不也曾用铁蹄践踏过大半个中国吗?闽粤沿 海的“侨乡”美誉不是被西洋人抓去的“猪猡”(或称“苦力”――COOLY,注意:“COOLY”就如此悲惨地成了英语的外来词!!!)的男士们用鲜血和 生命换来的吗?“横贯北美之铁路的每一根枕木下都躺卧着一个华工的冤魂”――没有听说一位正直的美国诗人曾写过这样的义愤填膺的诗句吗?还有:当年在上海 滩跟着英国人屁股后面混的“印度阿三”(也许是沾了点雅弗的血缘关系的含系后裔,被大英帝国殖民的历史还要长呢!!!)不是也敢对租界内外大清王朝的臣民 们指手画脚吗?也许他们嚷嚷“华人与狗不得入内”比当时的英国人还起劲呢!---整个一幅“奴仆的奴仆”的活图画!!!同为含系后裔的非洲大陆不也曾一度被英法葡荷等列强彻底瓜分并殖民得奄奄一息毫无生机吗?臭名昭著的黑奴贸易难道不值得雅弗的子孙们痛定思痛深刻反省吗?

“雅弗必扩张”的预言更是应验到家了:曾被含系后 裔(美洲印第安人:他们也保留了许多象形文字的文物古迹)占据几千年之久的美洲大陆几百年前被英法西葡等列强完全殖民,印第安人明明是原始主人,后来却有 了“哥伦布发现新大陆”的强盗说法!印第安人的话语权到那里去了?!美国、澳大利亚、新西兰等其实就是英国的替代者(扩张的结果)。欧洲文明鼻祖的希腊人 (以色列人对他们仍用旧约圣经的称呼“雅完”Yavan,或Iavan)至今仍然承认自己是“雅弗”的后裔。还有,特别喜欢扩张的俄国人(旧约称为“罗 示” Rusi)也是雅弗的后裔,仅十九世纪就从清朝政府手中割去一百五十多万平方公里的领土!如今的俄国首都虽远在莫斯科,却能控制广袤的西伯利亚的北极、东 端和南界。再想想含系的一代天骄成吉思汗及其儿孙们虽然也有打到莫斯科的历史记录,如今的蒙古国却在中俄两国的夹缝中生存,辉煌不再!在这里略微提一下: 把基督教称为“洋教”的说法其实非常非常的外行:圣经(包括旧约和新约全部六十六本书)的几十位作者除了一个路加(注:《路加福音》和《使徒行转》二书的 作者)是希腊医生之外,全部都是犹太人!福音(救恩)首先临到的是犹大人而根本不是“西洋人”;相反,是使徒保罗(希伯来人生的希伯来人)把福音传到了欧 洲。欧洲(包括后来的美洲)一千多年以来基督徒比例较高的事实正是“住在闪的帐棚里”这话的应验。


若反问为什么历史上强大的中国曾经也大大地扩张,并拥有附庸国一大堆,怎么解答?
是的,没错!不过这些“扩张”全是在含系的土地上:东夷南越西戎北胡都是 含系后裔,也就是说,蒙藏壮羌都是属含的。大明王朝的郑和七下西洋除了给蛮夷之邦送送温暖之外还给世界留下什么了呢?至于汉族和汉朝的“汉”,韩国的 “韩”还有“汉城”(注:近年才被“去中国化”之心极强的韩国人改成“首尔”,但韩国人也毫无疑问是“含”的后裔)的“汉”与那个挪亚之子“含”有没有必 然联系目前还没有特别的考证。然而根据三星堆遗址发现的文物就可以推断:成都平原三千年前的文明与两河流域的文明极可能有很大的内在关系。两河流域是一个 闪、含系民族长期混居的地方,闪系的亚伯拉罕就是离开了含系聚居的偶像之邦迦勒底之后才去应许之地的,所以被称为“希伯来人”--“越过(河)的人”。亚 伯拉罕是犹太人和阿拉伯人共认的祖先,只是阿拉伯人将这同一个人读作“易不拉欣”而已,如同把雅各读作“雅各布”,约瑟读作“尤素福”一样。


如果说炎黄子孙是闪的后裔,那么“闪的神”这个说法就实在不对了!炎黄子孙里没有多少人(百分比极低)认识闪的神;相反,对于来自牛鬼蛇神之邦(指印度)的偶像倒是趋之若鹜!也许轩辕黄帝所祭拜的“天”还和“闪的神”有 关系,但是他的子孙们后来却自称为“龙的传人”了。本文在这里不讨论关于中华民族“龙图腾”的问题。其实越南人也十分想自称为“龙的传人”呢!甚至中国和 印度之间的小国不丹(好像没有人认为这个国家有多重要)更干脆:国旗中间就是画了一个和中国人想象中一模一样的一条龙!关于新约最后一卷书《启示录》十二 章所指的“大红龙”、“大龙”、“古蛇”、“魔鬼”、“撒但”指的是谁,智者见智,仁者见仁。现存的闪系主要民族如犹太人(与希伯来人、以色列人的称呼有 交叉又有区别)、阿拉伯人、伊朗人(波斯人)倒是正如挪亚所预言:只虔诚敬拜一个神。

中国人的祖先

公元前2458年挪亚方舟时代肆意了一年毁灭全地的大洪水退去之后,挪亚的三个儿子(闪、雅弗、含)就被分散迁徙了。如今大部分的阿拉伯人、犹太人、波斯 人是闪氏一族的后裔。雅弗的子孙多分布在如今的欧洲西北等地,包括英、法、德、意、葡、俄;当然几百年前被英国人占领,如今被白种人统治的美洲、澳大利 亚、新西兰(这些土地原是被含系后裔占领长达几千年之久的,如美洲印第安人)也是雅弗一族的。我感兴趣的是含系子孙。含有四个儿子,古实、麦西(也称埃 及)、弗、迦南。他们绝大部分分布在非洲、地中海、西亚等地,也有包括日本、印度、中国在内的远东太平洋岛屿部落。像非洲的黑人如俄塞俄比亚被考证是古实 的后裔,麦西是古埃及人的祖先,现今的利比亚是弗一族的。而中国人及部分以色列人则是迦南一支的。迦南的其中一个儿子叫西尼(Sini),据母语为希伯来 语的以色列各学者指出,西尼就特指包括港澳台在内的华人的总称。

在中国的学术界,神农即是闪(Shem)、黄帝是含(Ham)、炎帝就是雅弗(Japheth)了。他们是大洪水前100年即在挪亚(NOAH, 即女娲)500岁时生的。而挪亚(女娲)是玛土撒拉(伏羲)的孙子,也是亚当(Adam,即少典)和夏娃(Eve,即有娲)的第十代。要指出的是,中国人 并不是‘炎黄子孙’,我们其实是黄帝的后裔。因此以上述为根据的结论就很明了了,人类有个共同的祖先,就是公元前4114年被造的亚当和夏娃。亚当享年 930岁。《圣经-创世记》的第十章开始比较详细地记述了由挪亚的三个儿子开始的世界各部落的雏形和发展去向。

二.挪亚的三个儿子:

圣经内容引用: 创世记9:25-27
『迦南当受咒诅,必给他弟兄做奴仆的奴仆』
『耶和华闪的神,是应当称颂的,愿迦南作闪的奴仆』
『愿神使雅弗扩张,使他住在闪的帐棚里,又愿迦南作他的奴仆』

这就是挪亚基于对他三个儿子观察后,对他们子孙后裔的著名的预言。
著名圣经人类学者Arthur C. Custanc在他的五部专著之一《挪亚的三个儿子》中说明,人类三个基本层次的需求――灵(信仰层面)、体(物质层面)和智(精神/文化层面,)――是 如何由神命定而被挪亚一家的这三个分支来分担。历史已经用显著的方式证明了各个人种在各自杰出成就上的专特性。就挪亚的三个儿子来说,含的兴趣主要在于体 (科技、生活基本需求),雅弗在他的智力特征(学术、哲学、文化)上充分表现了他的天赋,闪则追求信仰层面。

漫长的人类历史已经逐步验证了挪亚的预言:『耶和华闪的神是应当称颂的』无疑藉此预言闪系将承担传扬真神上帝的任务。犹太教,伊斯兰教,与基督教都是一神 教,都是闪系一族所宣扬的。而在公元元年降为肉身的主耶稣也是闪系后裔。『愿神使雅弗扩张,使他住在闪的帐棚里』,这里的扩张意指在文化、学术、科学方面 影响世界;当然进行这些智力扩张的前提是先要有政治占领来支持的。挪亚说,使雅弗『住在闪的帐棚里』很确切地告诉我们,雅弗的后裔将分享与闪氏一样的属灵 信仰。十几个世纪以来大部分欧洲各国、以及如今的美洲各国都信奉上帝教,从这里就可以很好地验证。至于含的儿子『迦南当受咒诅』,给他弟兄做奴仆的奴仆, 以及做闪和雅弗的奴仆,很多学者认为,相对于闪和雅弗在属灵和学术上的贡献,含在于科技以及生活所需方面的贡献并非与他们有价值大小的差别,也并非真指仆 役。在含系中,最先的印刷术,航海术,文字,金属业以及衣食住行等基本生活层面上的发明创造为世界发展提供了基础的保障。
本人的观点与顶级圣经人类学者Arthur C. Custance一致。他著有《挪亚的三个儿子》(“Noah's Three Sons”)等圣经人类学丛书)