Я делаю следующее:
Слушаю диверт сокет, на который ipfw правилом заворачаватся все пакеты, в div_sock проверяется пересылать или не пересылать дальше пакет. Т.е. если "пересылать" то все ок, пакеты пересылаются, а если "не пересылать", то sendto мне говорит Can't assign requested address. Подскажите что я не так делаю. Спасибо.
#include ....
void div_sock()
{
sockd=socket(AF_INET, SOCK_RAW, IPPROTO_DIVERT);
bindPort.sin_family=AF_INET;
bindPort.sin_port=htons(atoi(cfg_param.DIVERT_PORT));
bindPort.sin_addr.s_addr=0;
bind_sockd = bind(sockd, (struct sockaddr *)&bindPort, sizeof(struct sockaddr_in));
fromlen = sizeof(struct sockaddr_in);
while(1) {
len = recvfrom(sockd, buf, 65535, 0, (struct sockaddr *)&from, &fromlen);
hdr_ip = (struct ip*)buf;
hdr_tcp = (struct tcphdr*)(buf + 4*hdr_ip->ip_hl);
............
access = check_access(......);
if(access)
{
setsockopt(sockd, IPPROTO_IP, IP_MULTICAST_IF, &(hdr_ip->ip_src), sizeof(hdr_ip->ip_src));
len = sendto(sockd, buf, len ,0, (struct sockaddr *)&from, fromlen);
}else{
setsockopt(sockd, IPPROTO_IP, IP_MULTICAST_IF, &(hdr_ip->ip_src), sizeof(hdr_ip->ip_src));
send_tcp(sockd,inet_addr("192.168.7.240"),hdr_ip->ip_src.s_addr,TH_RST, hdr_tcp -> th_dport, hdr_tcp->th_sport, hdr_tcp -> th_seq, hdr_tcp -> th_ack, rst_buf,strlen(rst_buf));
}
}
}
unsigned short in_chksum(u_short *addr, int len)
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
u_short answer = 0;
while (nleft > 1) {
sum += *w++;
nleft -= 2;
}
if (nleft == 1) {
*(u_char *)(&answer) = *(u_char *)w ;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return(answer);
}
//send_tcp
int send_tcp(int s,
unsigned int src,
unsigned int dst,
unsigned char flg,
unsigned short sport,
unsigned short dport,
unsigned int seq,
unsigned int ack,
char *data,
int dlen)
{
unsigned char pkt[1024];
struct ip *ip;
struct tcphdr *tcp;
struct sockaddr_in sa;
static int ip_id = 0;
struct pseudo {
unsigned int s;
unsigned int d;
char n;
char p;
unsigned short l;
} pseudo;
if (!ip_id) {
ip_id = htons(rand() % getpid());
}
ip = (struct ip *) pkt;
tcp = (struct tcphdr *) (pkt + sizeof(struct ip));
pseudo.s = src;
pseudo.d = dst;
pseudo.n = 0;
pseudo.p = IPPROTO_TCP;
pseudo.l = htons(sizeof(struct tcphdr) + dlen);
tcp->th_sport = htons(sport);
tcp->th_dport = htons(dport);
tcp->th_seq = htonl(seq);
tcp->th_ack = htonl(ack);
tcp->th_off = 5;
tcp->th_flags = flg;
tcp->th_win = htons(16384);
tcp->th_urp = 0;
tcp->th_sum = 0;
memmove(((char *) tcp) + sizeof(struct tcphdr),
data, dlen); /* baom. 1024 */
memmove(((char *) tcp) - sizeof(struct pseudo),
(char *) &pseudo, sizeof(struct pseudo));
tcp->th_sum = in_chksum((u_short *)(((char *) tcp) - sizeof(struct pseudo)),sizeof(struct pseudo) + sizeof(struct tcphdr) + dlen);
ip->ip_v = 4;
ip->ip_hl = 5;
ip->ip_tos = 0;
ip->ip_len = htons(sizeof(struct tcphdr) + sizeof(struct ip) + dlen);
ip->ip_id = ip_id++;
ip->ip_off = htons(0);
ip->ip_ttl = 64;
ip->ip_p = IPPROTO_TCP;
ip->ip_sum = 0;
ip->ip_src.s_addr = src;
ip->ip_dst.s_addr = dst;
// ip->ip_sum = in_chksum((u_short *)pkt, sizeof(struct ip) + sizeof(struct tcphdr) + dlen);
ip->ip_sum = 0;
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = dst;
sa.sin_port = 0;
if (sendto(s, pkt, sizeof(struct ip) + sizeof(struct tcphdr) + dlen,
0, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
perror("sendto");
return -1;
}
return 0;
}
int main()
{
div_sock();
return 0;
}