#include #include #include #include #include #include #include extern const char *__progname; static int s1; static int s2; static pid_t kid; static unsigned short int add_to_checksum(unsigned short int s, const unsigned char *data, int len) { unsigned long int ls; ls = s; for (;len>=2;len-=2,data+=2) ls += (data[0] * 256) + data[1]; if (len) ls += data[0] * 256; while (ls & ~0xffffUL) ls = (ls & 0xffff) + (ls >> 16); return(ls); } static void run_child(void) { int on; unsigned char data[256]; unsigned char ctl[64]; struct msghdr mh; struct iovec iov; int nr; on = 1; if (setsockopt(s1,SOL_SOCKET,SO_TIMESTAMP,&on,sizeof(on)) < 0) { fprintf(stderr,"%s: SOL_SOCKET/SO_TIMESTAMP setsockopt: %s\n",__progname,strerror(errno)); exit(1); } mh.msg_name = 0; mh.msg_namelen = 0; mh.msg_iov = &iov; mh.msg_iovlen = 1; mh.msg_control = &ctl[0]; mh.msg_controllen = sizeof(ctl); mh.msg_flags = 0; iov.iov_base = &data[0]; iov.iov_len = sizeof(data); nr = recvmsg(s1,&mh,0); printf("data %d, ctl %d\n",nr,(int)mh.msg_controllen); } static void run_parent(void) { unsigned char data[64]; struct sockaddr_in6 a; unsigned short int sum; sleep(1); bzero(&a,sizeof(a)); // XXX API botch a.sin6_family = AF_INET6; a.sin6_len = sizeof(a); bcopy("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1",&a.sin6_addr,16); data[0] = 128; data[1] = 0; data[4] = 0; data[5] = 0; data[6] = 0; data[7] = 0; bzero(&data[8],64-8); sum = add_to_checksum(add_to_checksum(0,&data[0],2),&data[4],64-4) ^ 0xffff; data[2] = sum >> 8; data[3] = sum & 0xff; if (sendto(s2,&data[0],64,0,(const void *)&a,a.sin6_len) < 0) { fprintf(stderr,"%s: sendto: %s\n",__progname,strerror(errno)); exit(1); } sleep(1); } int main(void); int main(void) { s1 = socket(AF_INET6,SOCK_RAW,IPPROTO_ICMPV6); if (s1 < 0) { fprintf(stderr,"%s: raw ICMP6 socket: %s\n",__progname,strerror(errno)); exit(1); } s2 = socket(AF_INET6,SOCK_RAW,IPPROTO_ICMPV6); if (s2 < 0) { fprintf(stderr,"%s: raw ICMP6 socket: %s\n",__progname,strerror(errno)); exit(1); } kid = fork(); if (kid < 0) { fprintf(stderr,"%s: fork: %s\n",__progname,strerror(errno)); exit(1); } if (kid == 0) run_child(); else run_parent(); return(0); }