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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

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

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

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


原始套接字的創建

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

參數:

family:協議族 這里寫?PF_PACKET

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

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

ETH_P_IP:IPV4數據包

ETH_P_ARP:ARP數據包

ETH_P_ALL:任何協議類型的數據包

返回值:

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

失敗( <0 ):出錯


實例如下:

// 所需頭文件 #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; }


獲取鏈路層的數據包

ssize_t recvfrom( ?int sockfd,?

void *buf,?

size_t nbytes,

int flags,

struct sockaddr *from,?

socklen_t *addrlen );

參數:

sockfd:原始套接字

buf接收數據緩沖區

nbytes:接收數據緩沖區的大小

flags套接字標志(常為0)

from這里沒有用,寫 NULL

addrlen:這里沒有用,寫 NULL

返回值:

成功:接收到的字符數

失敗:-1


實例如下:

#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));//獲取鏈路層的數據包int len = recvfrom(sock_raw_fd, buf, sizeof(buf), 0, NULL, NULL);printf("len = %d\n", len);return 0; }

混雜模式

默認的情況下,我們接收數據,目的地址是本地地址,才會接收。有時候我們想接收所有經過網卡的所有數據流,而不論其目的地址是否是它,這時候我們需要設置網卡為混雜模式


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


通過命令給 Linux 網卡設置混雜模式(需要管理員權限)

設置混雜模式:ifconfig eth0 promisc



取消混雜模式:ifconfig eth0 -promisc



通過代碼給 Linux?網卡設置混雜模式



代碼如下:

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


發送自定義的數據包:

ssize_t sendto( ? int sockfd,

const void *buf,

size_t nbytes,int flags,

const struct sockaddr *to, ? ? ? ?

socklen_t addrlen );

參數:

sockfd原始套接字

buf發送數據緩沖區

nbytes:發送數據緩沖區的大小

flags一般為 0

to本機網絡接口,指發送的數據應該從本機的哪個網卡出去,而不是以前的目的地址

addrlen:to 所指向內容的長度

返回值:

成功:發送數據的字符數

失敗: -1


本機網絡接口的定義



發送完整代碼如下:

[cpp]?view plaincopy
  • struct?sockaddr_ll?sll;?????????????????//原始套接字地址結構??
  • struct?ifreq?req;???????????????????//網絡接口地址??
  • ??
  • strncpy(req.ifr_name,?"eth0",?IFNAMSIZ);????????????//指定網卡名稱??
  • if(-1?==?ioctl(sock_raw_fd,?SIOCGIFINDEX,?&req))????//獲取網絡接口??
  • {??
  • ????perror("ioctl");??
  • ????close(sock_raw_fd);??
  • ????exit(-1);??
  • }??
  • ??
  • /*將網絡接口賦值給原始套接字地址結構*/??
  • bzero(&sll,?sizeof(sll));??
  • sll.sll_ifindex?=?req.ifr_ifindex;??
  • ??
  • //?發送數據??
  • //?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


    總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。