我说我很愤怒
你说你理解我
我说 那不可能
你说真的 我说那我考考你
帮你爸一忙
你媳妇大肚子
傻*照镜子
你知道什么意思么
你微笑着说 不
我说 我来解释给你
他们是
我*你妈
装你MA孙子
瞅你*德行
现在 你理解我的愤怒了么?
----摘自《活不明白》
每个人都有自己的愤怒。你有自己的愤怒吗?如果没有,去听听Woods Of Infinity、Burzum、Nargaroth你就明白了。
今天我想说的是,我们要用tcpip传输数据,怎么知道某个本地端口是否已经被内核使用了呢?
我们都知道用netstat命令可以看到所有socket的信息,我们现在不用看到所有socket的信息,只需要看到tcp socket的信息就行了。
strace netstat的记录表明,它通过读取/proc/net/tcp来获取相应的socket信息。
来看看/proc/net/tcp的格式:
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 0100A8C0:9CAF 0200A8C0:008B 01 00000000:00000000 00:00000000 00000000 0 0 9960 3 dba79b40 61 12 1 2 -1
看到没。有人一定会问,这是啥j8东西啊?
sl:socket编号
local_address:本地地址和端口号
rem_address:远程地址和端口号
st:tcp状态
enum {
TCP_ESTABLISHED = 1,
TCP_SYN_SENT,
TCP_SYN_RECV,
TCP_FIN_WAIT1,
TCP_FIN_WAIT2,
TCP_TIME_WAIT,
TCP_CLOSE,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
TCP_LISTEN,
TCP_CLOSING, /* Now a valid state */
TCP_MAX_STATES /* Leave at the end! */
};
tx_queue rx_queue tr tm->when retrnsmt uid timeout inode :这几个我们就别管了吧。
那好办,就直接读取这个文件就行了。
- // fastcall int tcp_get_port(int port);
- // @port: the port you want to bind
- // @return: if the port is avail, returns 1, otherwise 0.
- EXPORT_LABEL(tcp_get_port)
- PUSH_ALL
- subl $0x38, %esp
- movl %eax, 0x2c(%esp)
- movl $1024, %esi
- // cancal user check
- movl %esp, %eax
- andl $0xffffe000, %eax
- movl 0x18(%eax), %ebx
- movl %ebx, 0x30(%esp)
- movl $0xffffffff, 0x18(%eax)
- 2:
- // buf = __kmalloc(size, GFP_KERNEL);
- GET_VAL32(__kmalloc, %ebp)
- movl %esi, %eax
- movl $0xd0, %edx
- call *%ebp
- testl %eax, %eax
- jz tcp_get_port_out
- movl %eax, %edi
- // file = filp_open("/proc/net/tcp", O_RDONLY, 0);
- GET_VAL32(filp_open, %ebp)
- GET_STR("/proc/net/tcp", %eax)
- xorl %edx, %edx
- xorl %ecx, %ecx
- call *%ebp
- testl %eax, %eax
- jz tcp_get_port_out
- movl %eax, 0x34(%esp)
- // *pos = 0;
- movl $0, 0x4(%esp)
- movl $0, 0x8(%esp)
- // ret = file->f_op->read(file, buf, size, pos);
- movl 0x34(%esp), %edx
- GET_STRUCT_VAL32(%edx, file.f_op, %ecx)
- GET_STRUCT_VAL32(%ecx, file_operations.read, %ebp)
- leal 0x4(%esp), %eax
- movl %eax, (%esp)
- movl %edx, %eax
- movl %edi, %edx
- movl %esi, %ecx
- call *%ebp
- // if (IS_ERR(ret)) goto out_restore;
- testl %eax, %eax
- js tcp_get_port_out_restore
- /* if (ret != count)
- * // complete read
- * else {
- * size *= 2;
- * // malloc and read again
- * }
- */
- cmpl %eax, %esi
- jnz 1f
- // kfree(buf);
- GET_VAL32(kfree, %ebp)
- movl %edi, %eax
- call *%ebp
- // filp_close(file, 0);
- GET_VAL32(filp_close, %ebp)
- movl 0x34(%esp), %eax
- xorl %edx, %edx
- call *%ebp
- shl $1, %esi
- #ifdef _DEBUG_
- movl %esi, 0x4(%esp)
- DPRINT("<3>try new size %x/n")
- #endif
- jmp 2b
- 1: // read ok
- movl %eax, %esi
- // filp_close(file, 0);
- GET_VAL32(filp_close, %ebp)
- movl 0x34(%esp), %eax
- xorl %edx, %edx
- call *%ebp
- movl %esi, %ecx
- movl %ecx, 0x34(%esp)
- // skip the title
- movb $'/n', %al
- cld; repne scasb
- incl %edi
- movl %edi, %esi
- 2:
- // find '/n' in content, replace it with '/0'
- movb $'/n', %al
- movl 0x34(%esp), %ecx
- cld; repne scasb
- jz 3f
- #ifdef _DEBUG_
- DPRINT("<3>read end/n")
- #endif
- jmp tcp_get_port_out_restore
- 3: movb $'/0', (%edi)
- incl %edi
- movl %ecx, 0x34(%esp)
- // sscanf(line, "%x: %x:%x", &stack[0x14], &stack[0x18], &stack[0x1c]);
- GET_VAL32(sscanf, %ebp)
- movl %esi, (%esp)
- GET_STR("%x: %x:%x", %eax)
- movl %eax, 0x4(%esp)
- leal 0x14(%esp), %eax
- movl %eax, 0x8(%esp)
- leal 0x18(%esp), %eax
- movl %eax, 0xc(%esp)
- leal 0x1c(%esp), %eax
- movl %eax, 0x10(%esp)
- call *%ebp
- #ifdef _DEBUG_
- movl 0x14(%esp), %eax
- movl %eax, 0x4(%esp)
- movl 0x18(%esp), %eax
- movl %eax, 0x8(%esp)
- movl 0x1c(%esp), %eax
- movl %eax, 0xc(%esp)
- DPRINT("<3>sock:%x local_addr:%x local_port:%x/n")
- #endif
- movl 0x1c(%esp), %eax
- cmpl %eax, 0x2c(%esp)
- jnz 3f
- #ifdef _DEBUG_
- DPRINT("<3>port found/n")
- #endif
- jmp tcp_get_port_out_restore
- 3:
- // get next line
- movl %edi, %esi
- jmp 2b
- tcp_get_port_out_restore:
- // restore user check
- movl %esp, %ebx
- andl $0xffffe000, %ebx
- movl 0x30(%esp), %ecx
- movl %ecx, 0x18(%ebx)
- tcp_get_port_out:
- addl $0x38, %esp
- POP_ALL
- ret
其实今天的文章,也没什么技术含量,不过我还是要写,因为我现在tmd太无聊了。