DF-0354 / ra_test.c
/* Standalone single-RA injection test - check if RA arrives in icmp6 */ #include <sys/fcntl.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/ip6.h> #include <netinet/icmp6.h> #include <net/ethernet.h> struct pi { uint8_t t,l,pl,fl; uint32_t v,p,r; struct in6_addr prefix; }; static uint16_t cksum6(const struct in6_addr*s,const struct in6_addr*d,const void*p,size_t l){ uint32_t sum=0; const uint16_t*q=p; size_t i; for(i=0;i+1<l;i+=2) sum+=ntohs(q[i]); if(i<l) sum+=((uint16_t)((const uint8_t*)p)[i])<<8; for(i=0;i<8;i++){sum+=ntohs(s->__u6_addr.__u6_addr16[i]);sum+=ntohs(d->__u6_addr.__u6_addr16[i]);} sum+=l; sum+=IPPROTO_ICMPV6; while(sum>>16) sum=(sum&0xffff)+(sum>>16); return htons(~sum&0xffff); } int main(int argc,char**argv){ const char*path=argc>1?argv[1]:"/dev/tap0"; int fd=open(path,O_RDWR); if(fd<0){perror("open");return 1;} unsigned char pkt[256]; size_t off=0; struct ether_header*eh=(void*)pkt; eh->ether_dhost[0]=0x33;eh->ether_dhost[1]=0x33;eh->ether_dhost[2]=0;eh->ether_dhost[3]=0;eh->ether_dhost[4]=0;eh->ether_dhost[5]=1; eh->ether_shost[0]=0x02;eh->ether_shost[1]=0xaa;eh->ether_shost[2]=0xbb;eh->ether_shost[3]=0;eh->ether_shost[4]=0;eh->ether_shost[5]=0xcc; eh->ether_type=htons(ETHERTYPE_IPV6); off+=sizeof(*eh); struct ip6_hdr*ip6=(void*)(pkt+off); ip6->ip6_flow=0; /* 4-byte union with vfc — set FIRST */ ip6->ip6_vfc=0x60; /* then version=6, traffic class=0 */ ip6->ip6_plen=htons(sizeof(struct nd_router_advert)+sizeof(struct pi)); ip6->ip6_nxt=IPPROTO_ICMPV6;ip6->ip6_hlim=255; inet_pton(AF_INET6,"ff02::1",&ip6->ip6_dst); inet_pton(AF_INET6,"fe80::1",&ip6->ip6_src); off+=sizeof(*ip6); struct nd_router_advert*ra=(void*)(pkt+off); ra->nd_ra_type=ND_ROUTER_ADVERT;ra->nd_ra_code=0;ra->nd_ra_cksum=0; ra->nd_ra_curhoplimit=64;ra->nd_ra_flags_reserved=0; ra->nd_ra_router_lifetime=htons(1800);ra->nd_ra_reachable=0;ra->nd_ra_retransmit=0; off+=sizeof(*ra); struct pi*pi=(void*)(pkt+off); pi->t=3;pi->l=4;pi->pl=64;pi->fl=0xc0; pi->v=htonl(1800);pi->p=htonl(1800);pi->r=0; inet_pton(AF_INET6,"2001:db8:1::",&pi->prefix); off+=sizeof(*pi); ra->nd_ra_cksum=cksum6(&ip6->ip6_src,&ip6->ip6_dst,ra,sizeof(*ra)+sizeof(*pi)); ssize_t w=write(fd,pkt,off); printf("w=%zd len=%zu cksum=%04x\n",w,off,ntohs(ra->nd_ra_cksum)); sleep(1); close(fd); return 0; } |