일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Nodejs
- kmip
- SWIFT
- MFA
- OSX
- apple
- FIDO2
- openssl
- Xcode
- Android
- 안드로이드
- 인증
- 2FA
- otpkey
- 애플
- css
- OTP
- SwiftUI
- 앨범북
- SSL
- MSYS2
- SSH
- albumbook
- git
- MYSQL
- appres
- WebAuthn
- 앱스토어
- 앱리소스
- fido
Archives
- Today
- Total
인디노트
icmp 를 전송한 후 응답을 받아서 해당 응답이 어떤 전송건인지 확인하는 C 코드 본문
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <unistd.h>
#define PACKET_SIZE 4096
#define IP_HDR_SIZE sizeof(struct iphdr)
#define ICMP_HDR_SIZE sizeof(struct icmphdr)
// IP 체크섬 계산 함수
unsigned short checksum(void *b, int len) {
unsigned short *buf = b;
unsigned int sum = 0;
unsigned short result;
for (sum = 0; len > 1; len -= 2)
sum += *buf++;
if (len == 1)
sum += *(unsigned char *)buf;
sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16);
result = ~sum;
return result;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: %s <IP address>\n", argv[0]);
exit(1);
}
char *target_ip = argv[1];
int sockfd, sent, recv;
struct sockaddr_in addr, sender;
socklen_t sender_size = sizeof(sender);
char packet[PACKET_SIZE], recv_packet[PACKET_SIZE];
struct iphdr *ip_hdr = (struct iphdr *)packet;
struct icmphdr *icmp_hdr = (struct icmphdr *)(packet + IP_HDR_SIZE);
// ICMP 요청 생성
memset(packet, 0, PACKET_SIZE);
icmp_hdr->type = ICMP_ECHO;
icmp_hdr->code = 0;
icmp_hdr->un.echo.id = getpid();
icmp_hdr->un.echo.sequence = 0;
icmp_hdr->checksum = 0;
icmp_hdr->checksum = checksum(icmp_hdr, ICMP_HDR_SIZE);
// 소켓 생성
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sockfd < 0) {
perror("socket");
exit(1);
}
// 수신 타임아웃 설정
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) {
perror("setsockopt");
exit(1);
}
// 수신 대기
memset(&sender, 0, sizeof(sender));
memset(recv_packet, 0, PACKET_SIZE);
sent = sendto(sockfd, packet, IP_HDR_SIZE + ICMP_HDR_SIZE, 0, (struct sockaddr *)&addr, sizeof(addr));
if (sent < 0) {
perror("sendto");
exit(1);
}
recv = recvfrom(sockfd, recv_packet, PACKET_SIZE, 0, (struct sockaddr *)&sender, &sender_size);
if (recv < 0) {
perror("recvfrom");
exit(1);
}
// ICMP 응답 확인
ip_hdr = (struct iphdr *)recv_packet;
icmp_hdr = (struct icmphdr *)(recv_packet + IP_HDR_SIZE);
if (icmp_hdr->type == ICMP_ECHOREPLY && icmp_hdr->un.echo.id == getpid()) {
printf("Received ICMP echo reply from %s\n", inet_ntoa(sender.sin_addr));
} else {
printf("Received unexpected ICMP packet\n");
}
close(sockfd);
return 0;
}
위 코드에서 icmp_hdr->type이 ICMP_ECHOREPLY이고, icmp_hdr->un.echo.id가 현재 프로세스의 ID와 일치하면 해당 응답이 이전에 전송한 ICMP 요청에 대한 응답임을 확인할 수 있습니다. 이 경우에는 수신한 응답의 IP 주소를 출력합니다. 그렇지 않은 경우에는 예상하지 못한 ICMP 패킷을 수신했음을 알리는 메시지를 출력합니다. 코드에서 소켓을 생성하고, ICMP 요청을 생성하고, 요청을 전송하고, 응답을 수신하고, 응답을 확인하고, 소켓을 닫는 과정을 거칩니다.
반응형
'개발 플랫폼 및 언어 > 네트워크 기술' 카테고리의 다른 글
문자열로 된 ip4 주소를 unsigned char 형식으로 변환하는 C 코드 (0) | 2023.04.16 |
---|---|
linux 에서 C 로 대기하고 있다가 시그널을 발생하여 다른 함수에서 시그널을 보내면 깨어나서 함수를 실행하는 C 코드 (0) | 2023.04.15 |
iphdr 의 송신자주소 및 수신자 주소를 변경하는 C 함수 (0) | 2023.04.14 |
iphdr 의 check 계산 하는 C 코드 (0) | 2023.04.14 |
ethertnet 패킷 라우팅 C 코드 (0) | 2023.04.14 |
Comments