示例#1
0
int main(int argc, char** argv) {
    char devname[IFNAMSIZ];
    int ifd, pingd;
    fd_set fds;
    int maxfd;
    struct timeval tv;

    struct in_addr me;
    int mask, server;
    
    char packet[PACKLEN];
    int len,tmp;
    struct sockaddr_in sa;
    struct in_addr buf;
    socklen_t buflen;
    struct icmphdr* icmph;

    int iphl;
    int faddr, taddr;

    int id, seq=0;

    if(argc<3) {
        dbg("ICMP-Proxy, by koala_man\n");
        dbg("Usage: %s magic ip\n",argv[0]);
        dbg("Magic is any 2-char string, same for server and client\n");
        dbg("For clients: ip is the public address for the server\n");
        dbg("For servers: ip is the private /24-mask for clients\n");
        exit(1);
    }
    if(inet_aton(argv[2],&me)<0) {
        perror("inet_aton");
        exit(1);
    }
    if(argv[1][0]!=0) id=argv[1][1]<<8;
    id=id | argv[1][0];
    dbg("Using id %x\n",id);

    server=(((me.s_addr)>>24)&0xFF)==0;
    mask=htonl(me.s_addr);
    dbg("You're a %s\n",server?"server":"client");
    dbg("Mask is %d: %s\n",mask,ntoa(mask));

    strncpy(devname,"it%d",IFNAMSIZ);
    ifd=opentun(devname);
    dbg("Opened tun as %s\n",devname);

    if((pingd=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP))<0) {
        perror("socket");
        close(ifd);
        exit(3);
    }

    targets=(int*)calloc(256,sizeof(struct in_addr));
    
    maxfd=MAX(ifd,pingd)+1;
    FD_ZERO(&fds);
    
    while(1) {
        FD_SET(pingd,&fds);
        FD_SET(ifd,&fds);
        tv.tv_sec=8; //XXX
        tv.tv_usec=0;
        
        dbg("\n");
        tmp=select(maxfd,&fds,NULL,NULL,&tv);
        if(tmp==0) {
            if(server) continue;
            icmph=(struct icmphdr*) packet;
            icmph->type=ICMP_ECHO;
            icmph->code=0;
            icmph->checksum=0;
            icmph->un.echo.sequence=seq++;
            icmph->un.echo.id=id;
            tmp=(sizeof(struct icmphdr));
            icmph->checksum=in_sum(packet,tmp,0);
            buflen=sizeof(struct sockaddr);
            sa.sin_addr=me;
            sendto(pingd,packet,tmp,0,(struct sockaddr*)&sa,buflen);
            dbg("Ping!\n");
        } else {
            if(FD_ISSET(pingd,&fds)) {
                dbg("Got a ping\n");
                buflen=sizeof(struct sockaddr);
                len=recvfrom(pingd,packet,PACKLEN,0,(struct sockaddr*)&sa,&buflen);
                dbg("Recvfrom=%d\n",len);
                iphl=packet[0]&0x0F;
                dbg("Packet header: %d\n",iphl);
                if(iphl<5) { 
                    dbg("Bad packet, too short header.\n");
                    continue;
                }
                taddr=ntohl(((int*)packet)[3]); //tunnel from
                faddr=ntohl(((int*)packet)[iphl+8/4+3]); //packet from
                if(!(taddr==mask || (server && (faddr & ~0xff)==mask))) {
                    dbg("IP from wrong place\n");
                    dbg(" Is %s\n",ntoa(faddr));
                    dbg(" or %s\n",ntoa(taddr));
                    dbg(" Should be %s\n",ntoa(mask));
                    continue;
                } 
                icmph=(struct icmphdr*)(packet+iphl*4);
                if(icmph->type != ICMP_ECHOREPLY) {
                    dbg("Not ICMP_ECHOREPLY\n");
                    continue;
                }
                if(icmph->un.echo.id!=id) {
                    dbg("Wrong ID\n");
                    continue;
                }
                if((len-iphl*4)<20 || len>PACKLEN) {
                    dbg("Not sane size\n");
                    continue;
                }
                if(server) {
                    dbg("Setting %x to %x\n",faddr,taddr);
                    settarget(faddr & 0xff,htonl(taddr));
                }
                write(ifd,packet+iphl*4+8,len-iphl*4-8);
            } 
            if(FD_ISSET(ifd,&fds)) {
                dbg("Got from if\n");
                icmph=(struct icmphdr*) packet;
                icmph->type=ICMP_ECHOREPLY;
                icmph->code=0;
                icmph->checksum=0;
                icmph->un.echo.sequence=htons(seq++);
                icmph->un.echo.id=id;
                
                len=read(ifd,packet+8,TUNLEN);  
                dbg("read=%d\n",len);
                if(len<0) {
                    perror("Read from if");
                    exit(4);
                }
                if(len==0) {
                    dbg("no data, lol?\n");
                    continue;
                }
                icmph->checksum=in_sum(packet,8+len,0);

                buflen=sizeof(struct sockaddr);
                if(server) {
                    tmp=ntohl(((int*)packet)[8/4+4]);
                    buf.s_addr=findtarget(tmp&0xff);
                    if(buf.s_addr==0) {
                        dbg("Don't know where to send, dropping\n");
                        continue;
                    }
                    sa.sin_addr=buf;
                } else {
                    sa.sin_addr=me;
                }
                sendto(pingd,packet,len+8,0,(struct sockaddr*)&sa,buflen);
            }
        }
    }
 
    buflen=sizeof(struct sockaddr);
    len=recvfrom(pingd,packet,PACKLEN,0,(struct sockaddr*)&sa,&buflen);
    dbg("Recvfrom=%d\n",len);
    write(2,packet,len);

    close(ifd);
    close(pingd);
    return 0;
    }
const Real GreensFunction2DAbs::p_int_theta_second(const Real r,
                                                   const Real theta,
                                                   const Real t) const
{
    const Real r_0(this->getr0());
    const Real a(this->geta());
    const Real minusDt(-1e0 * this->getD() * t);

    const Integer num_in_term_use(100);
    const Integer num_out_term_use(100);
    const Real threshold(CUTOFF);

    Real sum(0e0);
    Real term(0e0);
    Integer n(1);
    for(; n < num_out_term_use; ++n)
    {
        Real in_sum(0e0);
        Real in_term(0e0);
        Real in_term1(0e0);
        Real in_term2(0e0);
        Real in_term3(0e0);

        Real a_alpha_mn(0e0);
        Real alpha_mn(0e0);
        Real Jn_r_alpha_mn(0e0);
        Real Jn_r0_alpha_mn(0e0);
        Real Jn_d_1_a_alpha_mn(0e0);// J_n-1(a alpha_mn)
        Real Jn_p_1_a_alpha_mn(0e0);// J_n+1(a alpha_mn)

        Real n_real(static_cast<double>(n));
        int n_int(static_cast<int>(n));
        Integer m(1);

        for(; m < num_in_term_use; ++m)
        {
            a_alpha_mn = gsl_sf_bessel_zero_Jnu(n_real, m);
            alpha_mn = a_alpha_mn / a;
            Jn_r_alpha_mn     = gsl_sf_bessel_Jn(n_int, r * alpha_mn);
            Jn_r0_alpha_mn    = gsl_sf_bessel_Jn(n_int, r_0 * alpha_mn);
            Jn_d_1_a_alpha_mn = gsl_sf_bessel_Jn(n_int - 1, a_alpha_mn);
            Jn_p_1_a_alpha_mn = gsl_sf_bessel_Jn(n_int + 1, a_alpha_mn);

            in_term1 = std::exp(alpha_mn * alpha_mn * minusDt);
            in_term2 = Jn_r_alpha_mn * Jn_r0_alpha_mn;
            in_term3 = Jn_d_1_a_alpha_mn - Jn_p_1_a_alpha_mn;

            in_term = in_term1 * in_term2 / (in_term3 * in_term3);
            in_sum += in_term;

//                 std::cout << "inner sum " << in_sum << ", term" << in_term << std::endl;

            if(fabs(in_term/in_sum) < threshold)
            {
//                     std::cout << "normal exit. m = " << m << " second term" << std::endl;
                break;
            }
        }
        if(m == num_in_term_use)
            std::cout << "warning: use term over num_in_term_use" << std::endl;

//             term = in_sum * std::cos(n_real * theta);
        term = in_sum * std::sin(n_real * theta) / n_real;
        sum += term;

//             std::cout << "outer sum " << sum << ", term" << term << std::endl;

        if(fabs(in_sum / (n_real * sum)) < threshold)
        {
            /* if n * theta is a multiple of \pi, the term may be zero and *
             * term/sum become also zero. this is a problem. sin is in a   *
             * regeon [-1, 1], so the order of term does not depend on     *
             * value of sin, so this considers only (in_sum / n_real).     */

//                 std::cout << "normal exit. n = " << n << " second term" << std::endl;
            break;
        }
    }
    if(n == num_out_term_use)
        std::cout << "warning: use term over num_out_term_use" << std::endl;

    return (8e0 * sum / (M_PI * a * a));
}