/
netprog.txt
166 lines (136 loc) · 7.8 KB
/
netprog.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
tfn2k fprobe rinetd
libnids提供了tcp流重组功能,这是lipcap所不具备的
iph host-endian:
ip_v
ip_h
ip_tos
ip_ttl
ip_p
<netinet/ip.h> struct ip
struct tcphdr udphdr, and another struct iphdr
常用的Socket类型有两种:流式Socket(SOCK_STREAM, TCP)和数据报式Socket(SOCK_DGRAM, UDP)
两个网络程序之间的一个网络连接包括五种信息:通信协议、本地协议地址、本地主机端口、远端主机地址和远端协议端口
linux下,如果一个进程帮定某个port,那当进程结束时,该port仍然会被继续占用几十秒,在这段时间内尝试对
该port的绑定都会返回失败。解决方法:调用setsockopt()启用SO_REUSERADDR属性
struct sock kernel net
struct socket interface to userspace
physdev match: using --physdev-out in the OUTPUT, FORWARD and POSTROUTING chains for non-bridged traffic is not supported anymore
int socket(int domain/family, int type, int protocol/family mem);
AF_ address family
PF_ protocol family
"The protocol family generally is the same as the address family", and subsequent standards use AF_* everywhere.
Address family identifies a collection of protocol with the SAME ADDRESS FORMAT,while protocol family identifies a collection of protocol having SAME ARCHITECTURE.
UNP V1, Ch4, the history of AF_ and PF_
2.6.25 dev_get_by_index(char *) -> dev_get_by_index(struct net*, char *) #include <net/net_namespace.h>; add &init_net as default struct net *
struct net_device.hard_header -> net_device->header_ops->create
2.6.32 adds a new boolean arg -- `int kern', to determine socket creating in userspace or kernel.
All protocol family domain has the structure:
struct net_proto_family {
int family;
int (*create)(struct net *net, struct socket *sock, int protocol, int kern);
struct module *owner;
};
The prototype __sock_create(..., int kern),
and normal calling routines:
userspace -> sys_socket -> sock_create() -> __sock_create(..., 0) -> *create(..., 0)
kernel -> sock_create_kern() -> __sock_create(..., 1) -> *create(..., 1)
sock_create() in a system call and you are creating a socket for the process
sock_create_kern() anywhere in the kernel and want to create a socket,
because you have some client or server running in kernel mode (e.g. nfs).
I think interrupts have to be enabled when calling any of these functions.
For the kernel one, ought to add
if (!kern)
return -EPERM; /* means operation not permitted */
While csmencaps walks userspace road, like socket(AF_CSME, ...), AF_CSME is user defined protocol family, namely the address family (AF_)
struct sockaddr_in {(在netinet/in.h中定义):
short int sin_family; /* Address family */
unsigned short int sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
unsigned char sin_zero[8]; /* Same size as struct sockaddr */
};
struct sockaddr {
unsigned short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
sizeof(struct sockaddr) == sizeof(struct sockaddr_in) == 16
mysock.sa_family=AF_INET;
mysock.sin_addr.s_addr=inet_addr("192.168.0.1");
The bind() function shall assign a local socket address address to a socket identified by descriptor socket that has no local
socket address assigned. Sockets created with the socket() function are initially unnamed; they are identified only by their
address family.
/* 由于IP协议簇的复杂性(如TCP的超时重传机制),在目的端可能会在先
* 收到一个IP包分片数据后又收到该IP包完整样式,即未分片的完整IP包。
* 因此,当系统收到一个IP包后,如果IP包没有被分片,首先在IP分片链
* 表中检查是否已经收到一些该IP包的分片数据,如果有则用此完整的
* 数据包代替已经收到的分片数据,即释放IP分片链表中的对应的数据,
* 之后将该IP包交TCP数据流重组模块。
IP_MF == 0 && offset == 0
ip header + ip data <-> netlink header + data
struct nlmsghdr {
__u32 nlmsg_len; /* Length of message */
__u16 nlmsg_type; /* Message type*/
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process PID */
};
nf: (never see type 3 PACKET_OTHERHOST)
add abr, with eth0/1, ping through the netbox to a machine bebind it
ip_pre_routing (bidirection):
dev->name=abr, skb->dev->name=abr, pkt_type 0/2
ip_forward (bidirection):
dev->name=abr, skb->dev->name=eth0/1 (direction info), pkt_type 0/2
br_pre_routing:
ipv4/ip_input.c/ip_rcv() (only in):
some dev is abr, but can't catch what i want (i.e. ping pkt to the machine bebind the netbox), pkt_type 0/1/2/(3)
nfq:
can drop pack
1 pack can only be sent to 1 queue
can only get src-mac, no dst-mac
has mac-frame upper limit, drop the pack which is too large, i.e. 5k+
pcap:
libpcap在Linux上利用PACKET_SOCKET接口从链路层获取原始套结字数据包。原始套结字可以在用户空间被用来从IP头中获取所有的数据包
当内核的网络堆栈收到一个数据包时,要对其进行一定的校验以便确定是否有packet套结字对它感兴趣。
如果有的话,这个数据包就被分发给对它感兴趣的套结字。如果没有的话,这个数据包继续流向TCP层,UDP层,或者其它的真正目的地。
对于SOCKET_RAW型的套结字也是这样的情形。SOCKET_RAW非常类似于SOCKET_PACKET型的套结字,区别就在于SOCKET_RAW不提供链路层的头信息
can't drop pack, coz just a copy from kernel
only 1 thread, can't use multi
can get src-mac & dst-mac
pcap is a copy of network main stream
got a frame, but frame has no info about direction, so can't use in waf like device
socket(PF_PACKET
pcap_loop(handle, 0, callback, NULL); sniff forever, because count is 0
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present, max 1514 */
bpf_u_int32 len; /* length this packet (off wire) = iph->ip_len + 14 */
};
socket打开混杂模式
先sock=socket(PF_PACKET, SOCK_RAW,htons(ETH_P_IP)) 的方式打开Socket,然后再
ioctl(sock, SIOCGIFFLAGS, ðreq);
ethreq.ifr_flags |= IFF_PROMISC;
ioctl(sock, SIOCSIFFLAGS, ðreq);
打开混杂模式。
其实也就是Libpcap的实现方式吧?
--fpnp2-------------------------------------------------------------------------------------------------
Chapter 1
.1 is gateway default, not forced
DF flag (Don't Fragment) set (TCP) -- gateway discards and send ICMP back to notice sender to split it
unset (UDP)-- gateway split it
Chapter 2
/etc/services all port map
portmap/rpcbind
--------------------------------------------------------------------------------------------------------
--fpnp1-------------------------------------------------------------------------------------------------
Chapter 2
fd = s.makefile('rw', 0) makefile([mode[, bufsize]]) -> file object
client send while server shutdown, no error report
use s.shutdown(1) after s.sendall()
s.sendall('GET %s HTTP/1.0\r\n\r\n' % filename)
try:
s.shutdown(1)
except socket.error, e:
print "error sending data (detected by shutdown): %s" % e
s.connect() is optional in UDP, s.sendto('', (host, port)) instead
Chapter 20
fork() copy socket (as fs) to child, so 2 connection, need to close both
--------------------------------------------------------------------------------------------------------