原始碼編譯方法:gcc -o syn syn.c
結果:在centos6上成功執行,用tcpdump抓包分析,傳送的對端有syn,ack包返回,一切正常。
過程:寫**時忘記了對tcph->protocol賦值,計算出得checksum老不對,資料報是成功發出去了,但是對端沒syn,ack包回,查了幾個小時,鬱悶死我~~~
疑問:ip->check為0是核心會計算ip頭的checksum,但是計算出得結果和我用ip_fast_csum得到的結果不一致,這是為何?標記一下,有結論再附上。
#include #include #include #include #include #include /* 資料報最大長度,無負載 */
#define max_pkg_size 80 /* ip header = 20 ~ 40, tcp header = 20 ~ 40; max = 80 */
/* 計算tcp校驗和的最大使用長度 */
#define max_psd_size 52 /* psd header = 12, tcp header = 20 ~ 40; max = 52 */
/* 資料報構造引數 */
struct st_args;
/* 用於計算tcp校驗和的偽頭部 */
struct psdhdr;
/* * 採用彙編計算ip頭部校驗和
* @param[in]: iph, ip頭指標;
* @param[in]: ihl, ip頭長度(4的倍數)
* * @return 16位校驗和
* */
static inline uint16_t ip_fast_csum(const void *iph, unsigned int ihl)
/* * 計算校驗和
* @param[in]: buffer, 待計算資料指標
* @param[in]: size, 資料長度
* * @return 校驗和
* */
uint16_t csum(uint16_t *buffer, int size)
if(size)
cksum = (cksum>>16) + (cksum&0xffff);
cksum += (cksum>>16);
return (uint16_t)(~cksum);}/*
* 除錯用的函式,用於輸出資料
* */
void data_dump(uint8_t *pdata, int len)}/*
* 資料報傳送函式,只構造了ip頭+tcp頭大小的長度;
* ip頭和tcp都無選項部分,tcp無負載資料
* @param[in]: parg, 構造資料報是採用的一些引數
* * @return -1, 傳送失敗;0, 傳送成功
* */
int send_pkg(struct st_args* parg)
; uint8_t psdheader[max_psd_size] = ;
struct iphdr *iph = (struct iphdr*)datagram;
struct tcphdr *tcph = (struct tcphdr*)(datagram + sizeof(struct iphdr));
struct tcp_options *tcpopt = (struct tcp_options*)(datagram + sizeof(struct iphdr)
+ sizeof(struct tcphdr));
struct psdhdr *psdh = (struct psdhdr*)psdheader;
struct tcphdr *tcph_psd = (struct tcphdr*)(psdheader + sizeof(struct psdhdr));
int sockfd = -1, ret = 0;
int optval = 1;
const int *poptval = &optval;
sockfd = socket(pf_inet, sock_raw, ipproto_tcp);
if(sockfd < 0)
iph->ihl = 5; /* header length, 5 * 4 = 20 bytes */
iph->version = 4; /* version, ipv4 */
iph->tos = 0; /* type of service, gernarel */
iph->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr); /* total length, iph + tcph = 32 bytes */
iph->id = htons(54321); /* identifcation */
iph->frag_off = htons(0x02 << 13); /* fragment offset field */
iph->ttl = 64; /* time to live */
iph->protocol = 6; /* protocol, tcp */
iph->check = 0; /* checksum */
iph->saddr = parg->saddr.sin_addr.s_addr; /* source address */
iph->daddr = parg->daddr.sin_addr.s_addr; /* dest address */
tcph->source = parg->saddr.sin_port; /* source port */
tcph->dest = parg->daddr.sin_port; /* dest port */
tcph->seq = random(); /* current sended packet sequence number */
tcph->ack_seq = 0; /* expect received next packet sequence number */
tcph->doff = sizeof(struct tcphdr) / 4; /* data position in the packet */
tcph->syn = 1; /* syn packet */
tcph->window = htons(65535); /* size of tcp window, freebsd uses this value */
tcph->check = 0; /* checksum */
tcph->urg_ptr = 0; /* urgent data position */
psdh->saddr = iph->saddr;
psdh->daddr = iph->daddr;
psdh->mbz = 0;
psdh->protocol = iph->protocol;
psdh->tcpl = htons(sizeof(struct tcphdr));
//data_dump(psdheader, sizeof(struct psdhdr));
memcpy(tcph_psd, tcph, sizeof(struct tcphdr));
tcph->check = csum((uint16_t*)psdheader, sizeof(struct psdhdr) + sizeof(struct tcphdr));
/* iph->check == 0時, 核心會自動計算校驗和 */
//iph->check = ip_fast_csum(datagram, iph->ihl);
if(setsockopt(sockfd, ipproto_ip, ip_hdrincl, poptval, sizeof(optval)) < 0)
ret = sendto(sockfd, datagram, iph->tot_len, 0,
(struct sockaddr*)&(parg->daddr), sizeof(parg->daddr));
if(ret < 0)
//data_dump(datagram, 40);
close(sockfd);
return 0;
err_out:
if(sockfd != -1)
close(sockfd);
return -1;
}int main(int argc, char **argv)
, ,,};
while((arg = getopt_long(argc, argv, "s:p:d:f:", lopts, null)) != -1)
}memset(&args, 0, sizeof(struct st_args));
inet_pton(af_inet, sip, (void*)&args.saddr.sin_addr);
args.saddr.sin_port = htons(sport);
inet_pton(af_inet, dip, (void*)&args.daddr.sin_addr);
args.daddr.sin_port = htons(dport);
send_pkg(&args);
return 0;
}
Linux下用speedtest cli測網速
在linux 的命令列中使用speedtest cli來測試寬頻連線速度。wget chmod a rx speedtest cli.py sudo mv speedtest cli.py usr local bin speedtest cli sudo chown root root usr lo...
linux下用ssh傳輸檔案
使用linux登入遠端伺服器時,可以使用 sshfs user host dir mountpoint來掛載遠端的目錄,這樣就可以在本地訪問掛載的目錄。例如 我要把遠端伺服器192.168.100252的 home god目錄掛載到本地的 252目錄下,其中god是我在伺服器的使用者名稱 xhy x...
Linux 下用yum安裝mysql
1 檢視系統自帶mysql是否已安裝。root develop bin yum list installed grep mysql mysql libs.x86 64 5.1.73 5.el6 6 base 2 若有自帶安裝的mysql,將其解除安裝 root develop yum y remov...