#include #include #include #include #include #include #include "icmp.h" #define BUFSIZE (10*1024) static int icmp_socket = -1; guint16 ipsum(guint8 *p, guint l) { guint32 sum = 0; guint i; for (i = 0; i < l-1; i += 2) sum += (p[i] << 8) + p[i+1]; if (i < l) sum += p[i] << 8; sum = (sum & 0xFFFF) + (sum >> 16); sum = (sum & 0xFFFF) + (sum >> 16); return ~sum; } int reply_icmp_error(ipq_packet_msg_t *m, int code) { static guint8 buf[BUFSIZE]; struct iphdr* ip = (struct iphdr*) m->payload; struct icmphdr *icmp = (struct icmphdr*) buf; guint l, tl; struct sockaddr_in sa; icmp->type = 3; icmp->code = code; icmp->checksum = 0; icmp->un.frag.__unused = 0; icmp->un.frag.mtu = 0; l = ip->ihl*4 + 8; memcpy(&buf[sizeof(struct icmphdr)], m->payload, l); tl = l + sizeof(struct icmphdr); icmp->checksum = htons(ipsum((guint8*) icmp, tl)); sa.sin_family = AF_INET; sa.sin_port = 0; sa.sin_addr.s_addr = ip->saddr; if (sendto(icmp_socket, icmp, tl, 0, (struct sockaddr*) &sa, sizeof(sa)) < 0) { perror("sendto()"); return -1; } return 0; } int icmp_init() { int enable = 1; if ((icmp_socket = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) { perror("socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)"); return -1; } if (setsockopt(icmp_socket, SOL_SOCKET, SO_BROADCAST, (char *)&enable, sizeof(enable)) < 0) { perror("setsockopt(.., SOL_SOCKET, SO_BROADCAST)"); return -1; } return 0; } void icmp_done() { if (icmp_socket >= 0) close(icmp_socket); icmp_socket = -1; }