日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

【Linux网络编程】原始套接字编程

發(fā)布時間:2024/4/21 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux网络编程】原始套接字编程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原始套接字編程和之前的 UDP 編程差不多,無非就是創(chuàng)建一個套接字后,通過這個套接字接收數(shù)據(jù)或者發(fā)送數(shù)據(jù)。區(qū)別在于,原始套接字可以自行組裝數(shù)據(jù)包(偽裝本地 IP,本地 MAC),可以接收本機(jī)網(wǎng)卡上所有的數(shù)據(jù)幀(數(shù)據(jù)包)另外,必須在管理員權(quán)限下才能使用原始套接字。


原始套接字的創(chuàng)建

int socket ( int family, int type, int protocol );

參數(shù):

family:協(xié)議族 這里寫?PF_PACKET

type: ?套接字類,這里寫?SOCK_RAW

protocol:協(xié)議類別,指定可以接收或發(fā)送的數(shù)據(jù)包類型,不能寫 “0”,取值如下,注意,傳參時需要用?htons() 進(jìn)行字節(jié)序轉(zhuǎn)換。

ETH_P_IP:IPV4數(shù)據(jù)包

ETH_P_ARP:ARP數(shù)據(jù)包

ETH_P_ALL:任何協(xié)議類型的數(shù)據(jù)包

返回值:

成功( >0 ):套接字,這里為鏈路層的套接字

失敗( <0 ):出錯


實(shí)例如下:

// 所需頭文件 #include <sys/socket.h> #include <netinet/ether.h> #include <stdio.h> // perrorint main(int argc,char *argv[]) {int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) );if(sock_raw_fd < 0){perror("socket");return -1;}return 0; }


獲取鏈路層的數(shù)據(jù)包

ssize_t recvfrom( ?int sockfd,?

void *buf,?

size_t nbytes,

int flags,

struct sockaddr *from,?

socklen_t *addrlen );

參數(shù):

sockfd:原始套接字

buf接收數(shù)據(jù)緩沖區(qū)

nbytes:接收數(shù)據(jù)緩沖區(qū)的大小

flags套接字標(biāo)志(常為0)

from這里沒有用,寫 NULL

addrlen:這里沒有用,寫 NULL

返回值:

成功:接收到的字符數(shù)

失敗:-1


實(shí)例如下:

#include <stdio.h> #include <netinet/in.h> #include <sys/socket.h> #include <netinet/ether.h>int main(int argc,char *argv[]) {unsigned char buf[1024] = {0};int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));//獲取鏈路層的數(shù)據(jù)包int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);printf("len = %d\n", len);return 0; }

混雜模式

默認(rèn)的情況下,我們接收數(shù)據(jù),目的地址是本地地址,才會接收。有時候我們想接收所有經(jīng)過網(wǎng)卡的所有數(shù)據(jù)流,而不論其目的地址是否是它,這時候我們需要設(shè)置網(wǎng)卡為混雜模式


網(wǎng)卡的混雜模式一般在網(wǎng)絡(luò)管理員分析網(wǎng)絡(luò)數(shù)據(jù)作為網(wǎng)絡(luò)故障診斷手段時用到,同時這個模式也被網(wǎng)絡(luò)黑客利用來作為網(wǎng)絡(luò)數(shù)據(jù)竊聽的入口。在 Linux 操作系統(tǒng)中設(shè)置網(wǎng)卡混雜模式時需要管理員權(quán)限。在 Windows 操作系統(tǒng)和 Linux 操作系統(tǒng)中都有使用混雜模式的抓包工具,比如著名的開源軟件 Wireshark。


通過命令給 Linux 網(wǎng)卡設(shè)置混雜模式(需要管理員權(quán)限)

設(shè)置混雜模式:ifconfig eth0 promisc



取消混雜模式:ifconfig eth0 -promisc



通過代碼給 Linux?網(wǎng)卡設(shè)置混雜模式



代碼如下:

struct ifreq req; //網(wǎng)絡(luò)接口地址strncpy(req.ifr_name, "eth0", IFNAMSIZ); //指定網(wǎng)卡名稱 if(-1 == ioctl(sock_raw_fd, SIOCGIFINDEX, &req)) //獲取網(wǎng)絡(luò)接口 {perror("ioctl");close(sock_raw_fd);exit(-1); }req.ifr_flags |= IFF_PROMISC; if(-1 == ioctl(sock_raw_fd, SIOCSIFINDEX, &req)) //網(wǎng)卡設(shè)置混雜模式 {perror("ioctl");close(sock_raw_fd);exit(-1); }


發(fā)送自定義的數(shù)據(jù)包:

ssize_t sendto( ? int sockfd,

const void *buf,

size_t nbytes,int flags,

const struct sockaddr *to, ? ? ? ?

socklen_t addrlen );

參數(shù):

sockfd原始套接字

buf發(fā)送數(shù)據(jù)緩沖區(qū)

nbytes:發(fā)送數(shù)據(jù)緩沖區(qū)的大小

flags一般為 0

to本機(jī)網(wǎng)絡(luò)接口,指發(fā)送的數(shù)據(jù)應(yīng)該從本機(jī)的哪個網(wǎng)卡出去,而不是以前的目的地址

addrlen:to 所指向內(nèi)容的長度

返回值:

成功:發(fā)送數(shù)據(jù)的字符數(shù)

失敗: -1


本機(jī)網(wǎng)絡(luò)接口的定義



發(fā)送完整代碼如下:

[cpp]?view plaincopy
  • struct?sockaddr_ll?sll;?????????????????//原始套接字地址結(jié)構(gòu)??
  • struct?ifreq?req;???????????????????//網(wǎng)絡(luò)接口地址??
  • ??
  • strncpy(req.ifr_name,?"eth0",?IFNAMSIZ);????????????//指定網(wǎng)卡名稱??
  • if(-1?==?ioctl(sock_raw_fd,?SIOCGIFINDEX,?&req))????//獲取網(wǎng)絡(luò)接口??
  • {??
  • ????perror("ioctl");??
  • ????close(sock_raw_fd);??
  • ????exit(-1);??
  • }??
  • ??
  • /*將網(wǎng)絡(luò)接口賦值給原始套接字地址結(jié)構(gòu)*/??
  • bzero(&sll,?sizeof(sll));??
  • sll.sll_ifindex?=?req.ifr_ifindex;??
  • ??
  • //?發(fā)送數(shù)據(jù)??
  • //?send_msg,?msg_len?這里還沒有定義,模擬一下??
  • int?len?=?sendto(sock_raw_fd,?send_msg,?msg_len,?0?,?(struct?sockaddr?*)&sll,?sizeof(sll));??
  • if(len?==?-1)??
  • {??
  • ????perror("sendto");??
  • }??

  • 這里頭文件情況如下:


    #include <net/if.h>// struct ifreq #include <sys/ioctl.h> // ioctl、SIOCGIFADDR #include <sys/socket.h> // socket #include <netinet/ether.h> // ETH_P_ALL #include <netpacket/packet.h> // struct sockaddr_ll


    總結(jié)

    以上是生活随笔為你收集整理的【Linux网络编程】原始套接字编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。