|
|
<转载请注明出处>
1. ND协议介绍
邻居发现协议(Neighbor Discovery Protocol,以下称ND协议)是IPv6的一个关键协议,可以说,ND协议是IPv4某些协议在IPv6中综合起来的升级和改进,如ARP、ICMP路由器发现和ICMP重定向等协议。当然,作为IPv6的基础性协议,ND还提供了其他功能,如前缀发现、邻居不可达检测、重复地址检测、地址自动配置等。
1.1 IPv6协议格式

Version(4-bit):IP版本,该字段值为6
Traffic Class(8-bit):流量分类,与IPv4包头的TOS类似
Flow Label(20-bit):流标签,用来标记IPv6数据包的一个流
Payload Length(16-bit):有效载荷的长度,有效载荷为紧跟IPv6包头的数据包的其他部分
Next Header(8-bit):处理选项字段,分段,安全,移动性,松散源路由,记录路由等的新方式。该字段在承载ND报文时字段值为58(ICMPv6)。该字段详细字段值对应如下表
| Value |
Type of Header |
| 0 |
Hop-by-Hop Options Header |
| 6 |
TCP |
| 17 |
UDP |
| 41 |
Encapsulated IPv6 Header |
| 43 |
Routing Header |
| 44 |
Fragment Header |
| 50 |
Encapsulating Security Payload |
| 51 |
Authentication Header |
| 58 |
ICMPv6 |
| 59 |
No next header |
| 60 |
Destination Options Header |
Hop Limit:(8-bit):定义IP数据包所能经过的最大跳数,每跳一次将此值减1
Source Address(128-bit):IP数据包的源地址
Destination Address(128-bit):IP数据包的目的地址
继续阅读
一种IP的表示方式为192.168.1.1/24,其数字24的含义为24位掩码,即掩码为255.255.255.0,程序中读入的类似192.168.1.1/24的字符串可能需要转换为IP地址和掩码两个字符串保存或处理,即将192.168.1.1/24转换为192.168.1.1和255.255.255.0,一种程序的实现方法如下
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
int main()
{
char ip[] = "192.168.1.1/24";
uint8_t *ipPrint = NULL;
uint32_t ipAddr;
uint32_t *ipPtr = &ipAddr;
uint32_t mask = 0;
uint32_t value = 0;
uint32_t i = 0, j = 0;
uint8_t *ptr = NULL;
struct in_addr in;
ptr = strtok(ip, "/");
inet_aton(ptr, (struct in_addr *)ipPtr);
ptr = strtok(NULL, "/");
value = atoi(ptr);
for(i = 0; i<value; i++)
{
j = value-i-1;
mask |= 1<<j;
}
printf("%.8x\n%.8x\n",ipAddr,mask);
in.s_addr = ipAddr;
ipPrint = inet_ntoa(in);
printf("%s\n",ipPrint);
in.s_addr = mask;
ipPrint = inet_ntoa(in);
printf("%s\n",ipPrint);
return 0;
} |
This code modified from internet,insert IP and MAC to hashtable. Key is the last 16bit of MAC.
too busy without search and delete function, you can add them if your interested.
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
| #ifndef _ZHASH_H_
#define _ZHASH_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXHASHSIZE 16
#define ETH_ALEN 6
typedef struct _hashentry
{
void *key;
void *ipaddr;
void *mac;
struct _hashentry *next;
}hashentry;
typedef struct _hashtable
{
unsigned int (*gethash)(void *);
int (*compare)(void *,void *);
int hashsize;
int count;
hashentry **hashlist;
}hashtable;
typedef enum bool_t {
FALSE = 0,
TRUE
}bool;
hashtable *hash_create_t(unsigned int (*keyfunc)(void *),
int (*comparefunc)(void *,void *),
int size);
void hash_insert(void *key, void *ipaddr, void *mac, hashtable *tab);
unsigned int lh_strhash(void *src);
int equal_str(void *k1, void *k2);
void hash_print(hashtable *tab);
//void help();
#define hash_create(size) hash_create_t(lh_strhash,equal_str,size)
#define hashindex(key, tab) ((tab->gethash)(key)) % (tab->hashsize)
#endif |
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
| #include "zhash.h"
unsigned int lh_strhash(void * src)
{
int i, l;
unsigned long ret = 0;
unsigned short *s;
char *str = (char *)src;
if (str == NULL)
return(0);
l = (strlen(str) + 1) / 2;
s = (unsigned short *)str;
for (i = 0; i < l; i++)
ret ^= s[i]<<(i&0x0f);
return(ret);
}
int equal_str(void *k1, void *k2)
{
return (0 == strcmp((char *)k1, (char *)k2));
}
hashentry *hlist_new(void *key, void *ipaddr, void *mac)
{
hashentry *new = (hashentry *)malloc(sizeof(hashentry));
new->key = key;
new->ipaddr = ipaddr;
new->mac = mac;
new->next = NULL;
return new;
}
void hlist_append(hashentry **root, void *key, void *ipaddr, void *mac)
{
hashentry *new, *pos;
new = hlist_new(key, ipaddr, mac);
if(*root == NULL)
{
*root = new;
}
else
{
pos = *root;
while(pos->next != NULL)
pos = pos->next;
pos->next = new;
}
}
bool hlist_update(hashentry *root, void *key,void *ipaddr,void *mac,int (*compare)(void *,void *))
{
hashentry *pos;
for(pos = root; pos != NULL; pos = pos->next)
{
if(compare(key,pos->key))
{
// free(pos->ipaddr);
// free(pos->mac);
pos->ipaddr = ipaddr;
pos->mac = mac;
// free(key);
return TRUE;
}
}
return FALSE;
}
void hash_insert(void *key, void *ipaddr, void *mac, hashtable *tab)
{
unsigned int index = hashindex(key, tab);
hashentry *root = tab->hashlist[index];
if(!(hlist_update(root, key, ipaddr, mac, tab->compare)))
{
hlist_append(&tab->hashlist[index],key,ipaddr, mac);
tab->count++;
}
}
hashtable *hash_create_t(unsigned int (*keyfunc)(void *),
int (*comparefunc)(void *,void *),
int size)
{
int i;
int len = sizeof(hashentry *) * size;
hashtable *tab = (hashtable *)malloc(sizeof(hashtable));
memset (tab, 0, sizeof(hashtable *));
tab->hashlist = (hashentry**)malloc(len);
if(tab->hashlist == NULL)
{
free(tab);
return NULL;
}
memset(tab->hashlist,0,len);
for(i = 0; i<size; i++)
{
tab->hashlist[i] = NULL;
}
tab->gethash = keyfunc;
tab->compare = comparefunc;
tab->hashsize = size;
tab->count = 0;
return tab;
}
void hash_print(hashtable *tab)
{
int i;
int *p;
hashentry *temp;
printf("index\t%-20s\t%-20s\n","mac","ipaddr");
for(i = 0; i < MAXHASHSIZE; i++)
{
temp = tab->hashlist[i];
if(temp == NULL)
printf("%-d\t%-20s\t%-20s\n",i,"NULL","NULL");
else
printf("%d\t",i);
while(temp != NULL)
{
p = (int *)(temp->mac);
printf("%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\t",p[0],p[1],p[2],p[3],p[4],p[5]);
p = (int *)(temp->ipaddr);
const char *format = (temp->next == NULL)?("%d.%d.%d.%d\n"):("%d.%d.%d.%d -->\n\t");
printf(format,p[0],p[1],p[2],p[3]);
temp = temp->next;
}
}
}
/*
void help()
{
printf("command: \n");
printf(" -insert\n");
printf("\t--usage: insert mac ipaddr eg. insert 00:11:22:33:44:55 192.168.0.1\n");
printf("\t--description: insert mac,ip to hash table,mac divided by \":\",and ip by \".\"\n");
printf(" -del\n");
printf("\t--usage:del key eg.del 4455\n");
printf("\t--description: delete from hash table,key is the last 16 bits of mac\n");
printf(" -print\n");
printf("\t--usage: print\n");
printf("\t--description: print all over the hash table\n");
}*/ |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| #include "zhash.h"
int main(int argc, char **argv)
{
hashtable *tab = hash_create(MAXHASHSIZE);
unsigned int mac[ETH_ALEN]={0x00,0x68,0x30,0x3b,0x2a,0x56};
unsigned int ipaddr[4]={0xC0,0xA8,0x01,0x01};
unsigned int mac1[ETH_ALEN]={0x00,0x69,0x30,0x3b,0x2a,0x42};
unsigned int ipaddr1[4]={0xC0,0xA8,0x01,0x02};
char key[5];
// char key1[5];
memset(key,0,5);
// memset(key1,0,5);
sprintf(key,"%.2x%.2x",mac[4],mac[5]);
hash_insert((void *)key,(void *)ipaddr,(void *)mac,tab);
sprintf(key,"%.2x%.2x",mac1[4],mac1[5]);
hash_insert((void *)key,(void *)ipaddr1,(void *)mac1,tab);
hash_print(tab);
return 0;
} |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| CC = gcc
CFLAGS = -Wall -g
TARGET = zhash
SOURCE = \
zhash.c \
test.c
OBJS = $(SOURCE:%.c=%.o)
%.o:%.c
$(CC) $(CFLAGS) -c $< -o $@
$(TARGET):$(OBJS)
$(CC) $(OBJS) -o $@
clean:
@echo "cleanning object..."
-rm zhash *.o
@echo "clean finished!"
.PHONY:clean |
收集于网络
/* base.h:基本操作的位运算实现 */
#ifndef BASE_H
#define BASE_H
#define word int
#define uword unsigned int
/* 将最右侧的1位改成0位 */
#define right1to0(x) ((x)&((x)-1))
/* 向右传播最右侧的1位 */
#define right1torig(x) ((x)|((x)-1))
/* 将最右侧的连续1位串改成0位串 */
#define right1sto0s(x) (((x)|(x)-1)+1 & (x))
/* 检查无符号整数x是否为2的幂,注意&的优先级低于==,需要括号 */
#define powof2u(x) (((x)&((x)-1))==0)
/* 检查无符号整数x是否为2**n-1的形式 */
#define pow2sub1u(x) (((x)&((x)+1))==0)
/* 检查无符号整数x是否为2**j-2**k形式 */
#define pow2subpow2u(x) ((((x)|(x)-1)+1 & (x))==0)
/* 下列掩码直接析出字中指定的位 */
/* 析出最右侧的1位 */
#define right1(x) ((x) & -(x))
/* 析出最右侧的0位 */
#define right0(x) (~(x)&((x)+1))
/* 析出后缀0 */
#define suffix0(x) (((x)&-(x))-1)
/* 析出最右侧的1位和后缀0(即后缀10…0) */
#define suffix10s0(x) ((x) ^ (x)-1)
/* 下列掩码与字做&运算,可以析出字中指定的字段 */
/* 析出高阶n位(注意n的值不能大于int型的宽度) */
#define high_ones(n) (-1<<32-(n))
/* 析出低阶n位 */
#define low_ones(n) (~(-1<<(n)))
/* 析出低阶offset位和高阶32-offset-width位 */
#define mid_zeros(width,offset) \
(-1<<(width)+(offset) | ~(-1<<(offset)))
/* 析出中间width位,它右侧有offset位 */
#define mid_ones(width,offset) \
(~(-1<<(width)+(offset)) & (-1<<(offset)))
/* 对无符号整数x,求比x大且与x中的位1个数相同的下一个整数:
例如对nnn0 1111 0000,则下一个整数为nnn1 0000 01111。
可以用这个函数来遍历一个集合的所有子集 */
#define nextsame1u(x) (right1(x)+(x) | \
(((x)^right1(x)+(x))>>2)/right1(x))
/* 字的绝对值函数:注意x>>31为0或-1,而x^0=x,x^-1=~x */
#define abs(x) (((x)^((x)>>31))-((x)>>31))
/* 绝对值的负值 */
#define nabs(x) (((x)>>31)-((x)^((x)>>31)))
/* 符号扩展:将第7位向左传播(位编号从0开始) */
#define prop7thtolef(x) ((((x) & 0×000000FF) ^ 0×00000080)-0×00000080)
/* 对无符号整数实现算术右移:也可用更简单的((signed)(x)>>n) */
#define arithrshiftu(x,n) ((((x)^0×80000000)>>(n))-(0×80000000>>(n)))
/* 对有符号整数实现逻辑右移:也可用更简单的((unsigned)(x)>>n) */
#define logicrshift(x,n) ((((x)^0×80000000)>>(n))+(1<<31-(n)))
/* 符号函数:x>0返回1,x=0返回0,x<0返回-1 */
#define sign(x) (((x)>0)-((x)<0))
/* 三值比较函数:x>y返回1,x=y返回0,x<y返回-1 */
#define cmp(x,y) (((x)>(y))-((x)<(y)))
/* 符号传递函数:返回采用y的符号后的x */
#define copysign(x,y) ((abs(x)^((y)>>31))-((y)>>31))
/* 比较谓词:带符号整数 */
#define equal(x,y) (~((x)-(y)|(y)-(x))>>31)
#define noteq(x,y) (((x)-(y)|(y)-(x))>>31)
#define less(x,y) ((((x)^(y)) & ((x)-(y)^(x)) ^ (x)-(y))>>31)
#define larger(x,y) ((((y)^(x)) & ((y)-(x)^(y)) ^ (y)-(x))>>31)
#define lesseq(x,y) ((((x)|~(y)) & ((x)^(y) | ~((y)-(x))))>>31)
#define largereq(x,y) ((((y)|~(x)) & ((y)^(x) | ~((x)-(y))))>>31)
/* 比较谓词:无符号整数 */
#define equalu(x,y) (~((x)-(y)|(y)-(x))>>31)
#define notequ(x,y) (((x)-(y)|(y)-(x))>>31)
#define lessu(x,y) ((~(x) & (y) | ~((x)^(y)) & (x)-(y))>>31)
#define largeru(x,y) ((~(y) & (x) | ~((y)^(x)) & (y)-(x))>>31)
#define lessequ(x,y) (((~(x)|(y)) & (((x)^(y)) | ~((y)-(x))))>>31)
#define largerequ(x,y) (((~(y)|(x)) & (((y)^(x)) | ~((x)-(y))))>>31)
/* 溢出检测:带符号运算 */
#define addovf(x,y) ((~((x)^(y))&(((x)+(y))^(x)))>>31)
#define subovf(x,y) ((((x)^(y))&(((x)-(y))^(x)))>>31)
#define mulovf(x,y) ((y)<0 && (x)==0×80000000 || (y)!=0 && (x)*(y)/(y)!=(x))
#define divovf(x,y) ((y)==0 || (x)==0×80000000 && (y)==-1)
/* 溢出检测:无符号运算 */
#define addovfu(x,y) (~(x)<(y)) /* 也可用less(~(x),y) */
#define subovfu(x,y) ((x)<(y)) /* 也可用less(x,y) */
#define mulovfu(x,y) ((y)!=0 && (x) > 0xffffffff/(y))
#define divovfu(x,y) ((y)==0)
/* 循环移位:带符号整数 */
/* 循环左移n位 */
#define rotlshift(x,n) ((x)<<(n) | (unsigned)(x)>>32-(n))
/* 循环右移n位 */
#define rotrshift(x,n) ((unsigned)(x)>>(n) | (x)<<32-(n))
/* 循环移位:无符号整数 */
#define rotlshiftu(x,n) ((x)<<(n) | (x)>>32-(n))
#define rotrshiftu(x,n) ((x)>>(n) | (x)<<32-(n))
/* 正差函数:x>=y时返回x-y,x<y时返回0。注意&优先级高于^,无需要括号 */
#define doz(x,y) ((x)-(y)&~((x)-(y)^((x)^(y))&((x)-(y)^(x)))>>31)
/* 大值函数 */
#define max(x,y) ((y)+doz(x,y))
/* 小值函数 */
#define min(x,y) ((x)-doz(x,y))
/* 下面是无符号版本 */
#define dozu(x,y) ((x)-(y)& arithrshiftu(((x)|~(y))&((x)^(y)|~((x)-(y))) ,31))
#define maxu(x,y) ((y)+dozu(x,y))
#define minu(x,y) ((x)-dozu(x,y))
/* 交换变量的值 */
#define swap(x,y) \
do { x=x^y; y=y^x; x=x^y; } while(0)
/* 根据掩码来交换变量的相应字段:
当m的第i位为1时,交换x,y的第i位;当m的第i位为0时,保留x,y的第i位不变 */
#define swapbits(x,y,m) \
do { x=x^y; y=y^(x&(m)); x=x^y; } while(0)
/* 2个常量的循环赋值:当x为a时赋值b,当x为b时赋值a */
#define rottwo(x,a,b) do{ x=(a)^(b)^x; }while(0)
/* 3个常量的循环赋值 */
#define rotthree(x,a,b,c) \
do{ x=(-(x==c)&(a-c))+(-(x==a)&(b-c))+c; }while(0)
#endif
本文来自CSDN博客,原文出处:http://blog.csdn.net/zhoudaxia/archive/2010/03/28/5425619.aspx#
New blog borns.
It’s a cloudy day!
But have a nice mood today!
收集于网络
位运算
位运算的运算分量只能是整型或字符型数据,位运算把运算对象看作是由二进位组成的位串信息,按位完成指定的运算,得到位串信息的结果。
位运算符有:
&(按位与)、|(按位或)、^(按位异或)、~ (按位取反)。
其中,按位取反运算符是单目运算符,其余均为双目运算符。
位运算符的优先级从高到低,依次为~、&、^、|,
其中~的结合方向自右至左,且优先级高于算术运算符,其余运算符的结合方向都是自左至右,且优先级低于关系运算符。
(1)按位与运算符(&)
按位与运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 & 0 = 0, 0 & 1 = 0, 1 & 0 = 0, 1 & 1 = 1。
即同为 1 的位,结果为 1,否则结果为 0。
例如,设3的内部表示为
00000011
5的内部表示为
00000101
则3&5的结果为
00000001
按位与运算有两种典型用法,一是取一个位串信息的某几位,如以下代码截取x的最低7位:x & 0177。二是让某变量保留某几位,其余位置0,如以下代码让x只保留最低6位:x = x & 077。以上用法都先要设计好一个常数,该常数只有需要的位是1,不需要的位是0。用它与指定的位串信息按位与。
(2)按位或运算符(|)
按位或运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 | 0 = 0, 0 | 1 = 1, 1 | 0 = 1, 1 | 1 = 1
即只要有1个是1的位,结果为1,否则为0。
例如,023 | 035 结果为037。
按位或运算的典型用法是将一个位串信息的某几位置成1。如将要获得最右4为1,其他位与变量j的其他位相同,可用逻辑或运算017|j。若要把这结果赋给变量j,可写成:
j = 017|j
(3)按位异或运算符(^)
按位异或运算将两个运算分量的对应位按位遵照以下规则进行计算:
0 ^ 0 = 0, 0 ^ 1 = 1, 1 ^ 0 = 1, 1 ^ 1 = 0
即相应位的值相同的,结果为 0,不相同的结果为 1。
例如,013^035结果为026。
异或运算的意思是求两个运算分量相应位值是否相异,相异的为1,相同的为0。按位异或运算的典型用法是求一个位串信息的某几位信息的反。如欲求整型变量j的最右4位信息的反,用逻辑异或运算017^j,就能求得j最右4位的信息的反,即原来为1的位,结果是0,原来为0的位,结果是1。
继续阅读
协议的分析需要参考前一篇文章以太网帧格式,IP包头,TCP头格式说明。
抓取网络上的数据包需要设置网卡为混杂模式,调用recvfrom在创建的SOCK_RAW类型的socket上接收来自kernel的信息,然后再按照帧格式,IP头,TCP头格式,指针移动到相应位置并分析。
附上的小程序由于其他原因还在UDP9001端口监听了来自客户端的消息,这与本文无关。
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
|
#include <stdio.h> //for printf
#include <stdlib.h> //for exit
#include <string.h> // for strcmp
#include <sys/socket.h> //for socket,address
#include <sys/types.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <sys/ioctl.h> //for ioctl
#include <pthread.h>
#define INTERFACE "eth0"
#define BUFFLEN 2048
#define UDPPORT 9001
#define REQUEST 0
#define RESPONSE 1
#define RESERVE 2
#define z_print(fmt,args...) \
printf("[%s %d]"fmt"\n",__FILE__,__LINE__,##args)
typedef struct {
uint8_t version;
uint8_t type;
uint8_t len;
uint16_t number;
char data[255];
} datasend;
void* ch_hanlder();
uint8_t randvalue(); |
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
| #include "zhao_sock.h"
int main(int argc,char *argv[])
{
int sockfd;
int len;
int proto;
int port_s;
int port_d;
char recvbuff[BUFFLEN];
unsigned char type[4];
unsigned char *ethhead = NULL;
unsigned char *iphead = NULL;
unsigned char *p = NULL;
struct ifreq ifr;
pthread_t thread_ch;
pthread_create(&thread_ch,NULL,&ch_hanlder,NULL);
sockfd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL));
if (sockfd < 0)
{
z_print("socket create error");
exit(1);
}
strcpy(ifr.ifr_name,INTERFACE);
if (ioctl(sockfd,SIOCGIFFLAGS,&ifr) == -1)
{
z_print("set PROMISC fail!\n");
exit(1);
}
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(sockfd,SIOCGIFFLAGS,&ifr) == -1)
{
z_print("set PROMISC fail!");
exit(1);
}
while(1)
{
len = recvfrom(sockfd,recvbuff,sizeof(recvbuff),0,NULL,NULL);
if (len < 42)
{
z_print("receive error!");
continue;
}
ethhead = recvbuff; //frame head point
p = ethhead;
sprintf(type,"%02x%02x",p[12],p[13]); //frame type
if (strcmp(type,"0800") != 0) //0800 is IP frame
{
if (strcmp(type,"0806") == 0)
printf("protocol: ARP\n");
else if (strcmp(type,"8035") == 0)
printf("protocol: RARP\n");
else
printf("protocol: unknow\n");
printf("MAC:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x==>%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n\n", \
p[6],p[7],p[8],p[9],p[10],p[11],p[0],p[1],p[2],p[3],p[4],p[5]); //mac address
continue;
}
iphead = ethhead + 14; //ip head point
p = iphead + 12; //ip address
printf("IP:%d.%d.%d.%d==>%d.%d.%d.%d\n", \
p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]);
proto = (iphead + 9)[0]; //ip protocol
p = iphead + 20; //ip port
switch(proto)
{
case IPPROTO_ICMP:
printf("protocol: ICMP\n");
break;
case IPPROTO_IGMP:
printf("protocol: IGMP\n");
break;
case IPPROTO_IPIP:
printf("protocol: IPIP\n");
break;
case IPPROTO_TCP:
case IPPROTO_UDP:
printf("protocol: %s\n",(proto == IPPROTO_TCP) ? "TCP":"UDP");
port_s = (p[0]<<8)&0XFF00 | p[1]&0XFF; //source port
port_d = (p[2]<<8)&0XFF00 | p[3]&0XFF; // dest port
printf("source port:%u,",port_s);
printf("dest port:%u\n",port_d);
if (port_s == 80 || port_d == 80)
printf("protocol: HTTP\n");
else if (port_s == 67 || port_d == 67)
printf("protocol: DHCP\n");
else if (port_s == 21 || port_d == 21)
printf("protocol: FTP\n");
else if (port_s == 23 || port_d == 23)
printf("protocol: TELNET\n");
else if (port_s == 53 || port_d == 53)
printf("protocol: DNS\n");
else if (port_s == 137 || port_d == 137 || port_s == 138 || port_d == 138)
printf("protocol: NetBIOS/SMB\n");
else
printf("protocol: other\n");
break;
case IPPROTO_RAW:
printf("RAW\n");
break;
default:
printf("protocol:unknow(%d)\n",proto);
}
printf("\n");
}
}
void* ch_hanlder()
{
int sockfd;
int len;
int flag_close = 0;
socklen_t addrlen;
datasend msg_send;
datasend msg_recv;
struct sockaddr_in servaddr;
memset(&msg_send,0,sizeof(datasend));
memset(&msg_recv,0,sizeof(datasend));
bzero(&servaddr, sizeof(servaddr));
msg_send.version = 1;
msg_send.type = RESPONSE;
sprintf(msg_send.data,"%s","received!");
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(UDPPORT);
addrlen = sizeof(struct sockaddr_in);
if (bind(sockfd, (struct sockaddr *)&servaddr, addrlen) == -1)
{
perror("bind error");
exit(1);
}
while (1)
{
len = recvfrom(sockfd, &msg_recv, sizeof(datasend),0,(struct sockaddr*)&servaddr, &addrlen);
printf("version:%3d\n",msg_recv.version);
printf("type:%d\n",msg_recv.type);
printf("len:%d\n",msg_recv.len);
printf("number:%d\n",msg_recv.number);
printf("data:%s\n",msg_recv.data);
if (strcmp(msg_recv.data,"close") == 0)
{
sprintf(msg_send.data,"%s","close");
flag_close = 1;
}
msg_send.number = msg_recv.number + 1;
msg_send.len = randvalue();
sendto(sockfd,&msg_send,sizeof(datasend),0,(struct sockaddr*)&servaddr,addrlen);
if (flag_close)
break;
}
return;
}
uint8_t randvalue()
{
srand(time(0));
return (rand() % 255);
} |
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
| #include "zhao_sock.h"
int main(int argc, char *argv[])
{
int sockfd;
int len;
socklen_t addrlen;
struct sockaddr_in cliaddr;
FILE *fd;
datasend msg_send;
datasend msg_recv;
fd = fopen("/root/zhao_log.txt","a");
memset(&msg_send,0,sizeof(datasend));
memset(&msg_recv,0,sizeof(datasend));
bzero(&cliaddr, sizeof(cliaddr));
msg_send.version = 1;
msg_send.type = REQUEST;
msg_send.number = 1;
msg_send.len = randvalue();
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
cliaddr.sin_family = AF_INET;
cliaddr.sin_port = htons(UDPPORT);
cliaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
addrlen = sizeof(struct sockaddr_in);
while (1)
{
printf("please input send msg:");
scanf("%s",msg_send.data);
sendto(sockfd,&msg_send,sizeof(datasend),0,(struct sockaddr*)&cliaddr,addrlen);
len = recvfrom(sockfd, &msg_recv, sizeof(datasend),0,(struct sockaddr*)&cliaddr, &addrlen);
msg_send.number = msg_recv.number + 1;
msg_send.len = randvalue();
printf("version:%3d\n",msg_recv.version);
printf("type:%d\n",msg_recv.type);
printf("len:%d\n",msg_recv.len);
printf("number:%d\n",msg_recv.number);
printf("data:%s\n",msg_recv.data);
fprintf(fd,"version:%d\n",msg_recv.version);
fprintf(fd,"type:%d\n",msg_recv.type);
fprintf(fd,"len:%d\n",msg_recv.len);
fprintf(fd,"number:%d\n",msg_recv.number);
fprintf(fd,"data:%s\n",msg_recv.data);
if (strcmp(msg_recv.data,"close") == 0)
break;
}
fclose(fd);
return 0;
}
uint8_t randvalue()
{
srand(time(0)+1);
return (rand() % 255);
} |
 圖三、乙太網路的 MAC 訊框
在這個 MAC 當中,最重要的就是那個 6 Bytes 的目的與來源位址了! 事實上,在所有的乙太網路卡當中都有一個獨一無二的網路卡卡號, 那就是上頭的『目的與來源位址』,這個位址是硬體位址( hardware address ), 共有 6 bytes ,分別由 00:00:00:00:00:00 到 FF:FF:FF:FF:FF:FF, 這 6 bytes 當中,前 3bytes 為廠商的代碼,後 3bytes 則是該廠商自行設定的裝置碼了。 在 Linux 當中,你可以使用 ifconfig 這個指令來查閱你的網路卡卡號喔! 不過,由於 MAC 主要是與網路卡卡號有關,所以我們也常常將 MAC 作為網路卡卡號的代稱。 特別注意,在這個 MAC 的傳送中,他僅在區域網路內生效, 如果跨過不同的網域 (這個後面 IP 的部分時會介紹),那麼來源與目的的位址就會跟著改變了。 這是因為變成不同網路卡之間的交流了嘛!所以卡號當然不同了!如下所示:

圖四、在不同主機間持續傳送相同資料的 MAC 訊框變化
例如上面的圖示,我的資料要由電腦 A 通過 B 後才送達 C ,而 B 電腦有兩塊網路卡, 其中 MAC-2 與 A 電腦的 MAC-1 互通,至於 MAC-3 則與 C 電腦的 MAC-4 互通。 但是 MAC-1 不能與 MAC-3 與 MAC-4 互通,為啥?因為 MAC-1 這塊網路卡並沒有與 MAC-3 及 MAC-4 使用同樣的 switch/hub 相接嘛!所以,資料的流通會變成:
- 先由 MAC-1 傳送到 MAC-2 ,此時來源是 MAC-1 而目的地是 MAC-2;
- B 電腦接收後,察看該訊框,發現目標其實是 C 電腦,而為了與 C 電腦溝通, 所以他會將訊框內的來源 MAC 改為 MAC-3 ,而目的改為 MAC-4 ,如此就可以直接傳送到 C 電腦了。
也就是說,只要透過 B (就是路由器) 才將封包送到另一個網域 (IP 部分會講) 去的時候, 那麼訊框內的硬體位址就會被改變,然後才能夠在同一個網域裡面直接進行 frame 的流通啊!
MAC包大小:旧为1900bytes,大为9000bytes
IP 封包的表頭
現在我們知道 IP 這個資料封包 (packet) 是需要放置在 MAC 訊框裡面的,所以當然不能比 MAC 所能容許的最大資料量還大!但是 IP 封包其實可以到 65535 bytes 那麼大的吶! 那麼 IP 封包除了資料之外,他的表頭資料 (head) 是長怎樣呢? 在 圖三的 MAC 訊框表頭裡面最重要的莫過於那個網路卡硬體位址, 那麼在 IP 表頭裡面當然就以來源與目標的 IP 位址為最重要囉! 除此之外, IP 表頭裡面還含有哪些重要資料呢?如底下所示:(下圖第一行為每個欄位的 bit 數)

圖八、IP 封包的表頭資料
在上面的圖示中有個地方要注意,那就是『 每一行所佔用的位元數為 32 bits』, 也就是說, IP 封包的表頭資料是 32 bits 的倍數喔!那各個表頭的內容分別介紹如下:
继续阅读
发现很多公司面试都喜欢考链表,实际项目中尽管需要自己写链表的时候比较少,但还是会经常用到,链表是一种常用的数据结构。有必要整理一下自己的思路,索性写了一个。包括了链表的初始化,插入,删除,查找,销毁,打印等基本功能,当然考虑了头尾中间等位置情况。仓促完成的简单代码,bug比较多,链表中只存储了一个整形的变量,没有做数据类型的判断,有时候会段错误也难免。已知的一个问题就是创建的链表在有销毁前如果再创建一个的话,会造成内存泄露,因为之前的链表没有销毁头指针便指向了新的位置,旧链表就永远找不到哦。这些问题留在以后实际用到的时候再考虑吧,应付面试这个足矣!
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
167
168
169
170
171
172
| #include <stdio.h>
#include <stdlib.h>
typedef struct node_t {
int value;
struct node_t *next;
} node;
#define LENGTH sizeof(node)
node *init_node(){
int node_length,n=0;
node *head=NULL;
node *node_temp1,*node_temp2;
node_temp2=(node *)malloc(LENGTH);
printf("node length want to create:");
scanf("%d",&node_length);
if(node_length<1){
printf("no node to create!");
exit(0);
}
while(n<node_length){
node_temp1=(node *)malloc(LENGTH);
printf("input NO.%d value:",n+1);
scanf("%d",&node_temp1->value);
node_temp1->next=NULL;
if(n==0)
head=node_temp1;
else
node_temp2->next=node_temp1;
node_temp2=node_temp1;
n++;
}
return head;
}
node *insert_node(node *head){
int insert_value;
node *temp_node1=head;
node *temp_node2=(node *)malloc(LENGTH);
node *temp_node3=NULL;
printf("insert value:");
scanf("%d",&insert_value);
while(temp_node1!=NULL){
if(temp_node1->value<insert_value){
temp_node3=temp_node1;
temp_node1=temp_node1->next;
}
else
break;
}
temp_node2->value=insert_value;
if(temp_node3==NULL){/*locate the first node*/
temp_node3=head;
temp_node2->next=temp_node3;
head=temp_node2;
}
else if(temp_node1!=NULL){ /*locate the medium of head,insert between temp3 and temp1*/
temp_node2->next=temp_node3->next;
temp_node3->next=temp_node2;
}else{ /*locate the end of head*/
temp_node2->next=NULL;
temp_node3->next=temp_node2;
}
return head;
}
node *delete_node(node *head){
int del_value;
node *temp_node1=head;
node *temp_node2;
printf("input the delete value:");
scanf("%d",&del_value);
if(head->value==del_value){ /* delete the head of node*/
temp_node2=head;
head=head->next;
return head;
}
while(temp_node1!=NULL){
if(temp_node1->value!=del_value){
temp_node2=temp_node1;
temp_node1=temp_node1->next;
}
else
break;
}
if(temp_node1!=NULL){
temp_node2->next=temp_node1->next;
free(temp_node1);
}else
printf("not find what you want to delete!\n");
return head;
}
void search_node(node *head){
int search_value,n=1;
node *temp_node=head;
printf("insert the value which you find:");
scanf("%d",&search_value);
while(temp_node!=NULL){
if(temp_node->value!=search_value){
temp_node=temp_node->next;
n++;
}
else
break;
}
if(temp_node!=NULL)
printf("finded what you want.\nthe %d node`s value:%d\n",n,temp_node->value);
else
printf("not find!\n");
}
void print_node(node *head){
if(head==NULL){
printf("blank node!create first please!\n");
return;
}
node *temp_node=head;
do{
printf("value:%d\n",temp_node->value);
temp_node=temp_node->next;
} while(temp_node!=NULL);
}
node *destroy_node(node *head){
if(head==NULL){
printf("blank node!create first please!\n");
return;
}
node *temp_node;
do{
temp_node=head->next;
free(head);
head=temp_node;
}while(head!=NULL);
return head;
}
int main(){
int options;
node *head=NULL;
loop:
printf("select options:\t1:create 2:insert 3:delete 4:find 5:print 6:destory 7:exit\ninput options:");
scanf("%d",&options);
switch(options){
case 1:
head=init_node();
break;
case 2:
head=insert_node(head);
break;
case 3:
head=delete_node(head);
break;
case 4:
search_node(head);
break;
case 5:
print_node(head);
break;
case 6:
head=destroy_node(head);
break;
case 7:
printf("byebye!");
return 0;
default:
printf("invalid options!");
}
goto loop;
} |
如果上次的更换工作不算跳槽的话,这次的得算了。
简历改了一遍又一遍,拿着改满意的简历再和刚毕业那会的对比,发现了很多的不同。
主修过N多的课程统统的删掉了,因为发现很多名字都已经有些生疏了;带熟悉字眼的也统统干掉了,其实自己什么都不懂,难道会写个hello就说英语牛X了;精通的字眼大都改成了熟悉、了解,真佩服自己当年的肺活量,太能吹了;实话实说的写了一段自己做过什么,这才是最真实的一段了。
进了这个圈才知道,自己能圈住的原来寥寥无几。随着慢慢的圈住一些东西,才懂得自己应该圈住哪些,外面的世界太大了,抓住适合自己的,真正为我所用的才是关键。
虽说简历要展现自己,做的多么华丽,写的多么坚决,但现在看起来,这些指导让我颇有些心虚,为难。
拿着这份简历面试了一下午,这都是好几周前的事了。现在敢写出来也是因为已经不属于那里,也就不用怎么顾忌。其实人家看的也就是自己觉得最真实的那段。聊的很多东西都是关于具体的项目,职业的规划。看来刚毕业的一大段只能归结为凑字数。
曾经就听到之前的经理闲谈之间说到,凡是说精通的,顶多算个了解,说了解的,大概也就知道个名字。真是悲哀,大家心知肚明,却也只能这样。
真实过后,等我再去吹嘘的时候,应该能吹一个更大,大好几倍的泡泡,想想都觉得刺激。继续努力,鼓励自己了!
|
|
COMMENTS