Esempio n. 1
0
static int scan_ip6_port( const char *src, ot_ip6 ip, uint16 *port ) {
  const char *s = src;
  int off, bracket = 0;
  while( isspace(*s) ) ++s;
  if( *s == '[' ) ++s, ++bracket; /* for v6 style notation */
  if( !(off = scan_ip6( s, ip ) ) )
    return 0;
  s += off;
  if( *s == 0 || isspace(*s)) return s-src;
  if( *s == ']' && bracket ) ++s;
  if( !ip6_isv4mapped(ip)){
    if( ( bracket && *(s) != ':' ) || ( *(s) != '.' ) ) return 0;
    s++;
  } else {
    if( *(s++) != ':' ) return 0;
  }
  if( !(off = scan_ushort (s, port ) ) )
     return 0;
  return off+s-src;
}
Esempio n. 2
0
int main()
{
  unsigned char *remotehost, *remoteip, *remoteport, *localip, *localport;
  unsigned char query[256] = {0};
  uint32 uid = 0xffffffff;          // that's our default for "not found"
  int query_len = 0;
  int pos = 0;
  char *problem = "ok";
  stralloc answer = {0};
  char strnum[FMT_ULONG];
  int  proto = 0;
  char *x;
  char lip[16] = {0};
  char rip[16] = {0};
  uint16 lport = 0;
  uint16 rport = 0;

  didentd_init();

  x = env_get("PROTO");
  if(x)
    {
      if(str_equal(x, "TCP")) proto = 4;
      if(str_equal(x, "TCP6")) proto = 6;
    }
  
  if(proto == 0)
    {
      buffer_puts(buffer_2, "warning: can't determine $PROTO\n");
      buffer_flush(buffer_2);
    }

  srandom(((long long) getpid () *
	    (long long) time(0) *
	    (long long) getppid() * 
	    (long long) random() * 
	    (long long) clock()) % 0xffffffff);

  /* since we run under tcpserver, we can get all info 
     about the remote side from the enviroment */
  remotehost = env_get("TCPREMOTEHOST");
  if (!remotehost) remotehost = "unknown";
  remoteport = env_get("TCPREMOTEPORT");  
  if (remoteport) scan_ushort(remoteport, &rport); else remoteport = "0";
  localport = env_get("TCPLOCALPORT");
  if (localport) scan_ushort(localport, &lport); else localport = "0";

  remoteip = env_get("TCPREMOTEIP");
  if (!remoteip) remoteip = "0.0.0.0";
  localip = env_get("TCPLOCALIP");
  if (!localip) localip = "0.0.0.0";
  
  if(proto == 4)
    {
      if(remoteip) 
	ip4_scan(remoteip, rip);

      if(localip) 
	ip4_scan(localip, lip);
      
      /* seed some entropy into the by IPv4 unsused bytes */
      rip[5] = (char) random() & 0xff;
      rip[6] = (char) random() & 0xff;
    }

  if(proto == 6)
    {
      if (remoteip) 
	ip6_scan(remoteip, rip);

      if (localip) 
	ip6_scan(localip, lip);
    }

  /* Read the request from the client and \0-terminate it */
  /* timeout after 60 seconds */
  query_len = timeoutread(60, stdin, query, sizeof(query) - 1);
  query[query_len] = '\0';
     
  /* If there was any data we can go on */
  problem = "empty query";
  if (query_len > 0)
    {
      problem = "illegal query";
      pos = scan_ushort(query, &lport);
      if(query[pos++] == ' ')
	if(query[pos++] == ',')
	  if(query[pos++] == ' ')
	    {
	      pos = scan_ushort(&query[pos], &rport);
	      problem = "ok";
	      
	      if(proto == 4)
		uid = get_connection_info4(lip, lport, rip, rport);
	      if(proto == 6)
		uid = get_connection_info6(lip, lport, rip, rport);
	      
	      stralloc_copyb(&answer, strnum, fmt_ulong(strnum, lport));
	      stralloc_cats(&answer, " , ");
	      stralloc_catb(&answer, strnum, fmt_ulong(strnum, rport));
	      
	      if(uid != 0xffffffff)
		problem = generate_answer(&answer, uid, lip, lport, rip, rport);
	      else
		generate_answer(&answer, uid, lip, lport, rip, rport);
	      
	      buffer_puts(buffer_1, answer.s);
	      buffer_flush(buffer_1);
	    }
    }

  /* Do logging */
  buffer_puts(buffer_2, localip);  
  buffer_puts(buffer_2, ":");
  buffer_put(buffer_2, strnum, fmt_ulong(strnum, lport));
  buffer_puts(buffer_2, " -> ");
  buffer_puts(buffer_2, remoteip);  
  buffer_puts(buffer_2, ":");
  buffer_put(buffer_2, strnum, fmt_ulong(strnum, rport));
  buffer_puts(buffer_2, " [");
  buffer_puts(buffer_2, problem);
  buffer_puts(buffer_2, "] ");
  if(uid < 0xffffffff)
      buffer_put(buffer_2, strnum, fmt_ulong(strnum,uid));
  else
       buffer_puts(buffer_2, "unknown");  
  buffer_puts(buffer_2, "\n");
  buffer_flush(buffer_2);

  return 0;
}
Esempio n. 3
0
int main(int argc,char* argv[]) {
  char server[1024];
  int* fds;
  int* avail;
  int* keepleft;
  long long* expected;
  unsigned long n=10000;	/* requests */
  unsigned long c=10;		/* concurrency */
  unsigned long t=0;		/* time limit in seconds */
  unsigned long k=0;		/* keep-alive */
  unsigned long K=1;		/* keep-alive counter */
  int report=0;
  unsigned long long errors=0;
  unsigned long long bytes=0;
  int v=0;
  unsigned long i,done;
  uint16 port=80;
  uint32 scope_id=0;
  stralloc ips={0};
  char* request,* krequest;
  unsigned long rlen, krlen;
  tai6464 first,now,next,last;
  enum { SAME, REPLAY } mode;
  char* hostname;

  server[0]=0;

  errmsg_iam("bench");
#ifndef __MINGW32__
  signal(SIGPIPE,SIG_IGN);
#endif

  for (;;) {
    int i;
    int ch=getopt(argc,argv,"n:c:t:kvK:C:r");
    if (ch==-1) break;
    switch (ch) {
    case 'r':
      report=1;
      break;
    case 'n':
      i=scan_ulong(optarg,&n);
      if (i==0) die(1,"could not parse -n argument \"",optarg,"\".\n");
      break;
    case 'c':
      i=scan_ulong(optarg,&c);
      if (i==0) die(1,"could not parse -c argument \"",optarg,"\".\n");
      break;
    case 't':
      i=scan_ulong(optarg,&t);
      if (i==0) die(1,"could not parse -t argument \"",optarg,"\".\n");
      break;
    case 'k':
      k=1;
      break;
    case 'K':
      i=scan_ulong(optarg,&K);
      break;
    case 'v':
      v=1;
      break;
    case 'C':
      cookiefile(optarg);
      break;
    case '?':
      break;
    default:
      usage();
    }
  }
  if (n<1 || c<1 || !argv[optind]) usage();

  if (argv[optind][0]=='@') {
    mode=REPLAY;
    char* host;
    n=(unsigned long)-1;
    host=argv[optind]+1;
    {
      int tmp;
      tmp=str_chr(host,'/');
      if (host[tmp]) {
	host[tmp]=0;
	if (!scan_ushort(host+tmp+1,&port)) usage();
      }
      tmp=str_chr(host,'%');
      if (host[tmp]) {
	host[tmp]=0;
	scope_id=socket_getifidx(host+tmp+1);
	if (scope_id==0)
	  carp("warning: network interface \"",host+tmp+1,"\" not found.");
      }
    }

    {
      stralloc a={0};
      stralloc_copys(&a,host);
      if (dns_ip6(&ips,&a)==-1)
	die(1,"could not find IP for \"",host,"\"!");
    }
    hostname=host;
    request=krequest=0;
    rlen=krlen=0;
  } else {
    char* host=argv[optind];
    int colon;
    int slash;
    char* c;
    mode=SAME;
    if (byte_equal(host,7,"http://")) host+=7;
    colon=str_chr(host,':');
    slash=str_chr(host,'/');
    if (host[0]=='[') {	/* ipv6 IP notation */
      int tmp;
      ++host;
      --colon; --slash;
      tmp=str_chr(host,']');
      if (host[tmp]==']') host[tmp]=0;
      if (host[tmp+1]==':') colon=tmp+1;
      if (colon<tmp+1) colon=tmp+1+str_len(host+tmp+1);
    }
    if (colon<slash) {
      host[colon]=0;
      c=host+colon+1;
      if (c[scan_ushort(c,&port)]!='/') usage();
      *c=0;
    }
    host[colon]=0;
    c=host+slash;
    *c=0;
    {
      char* tmp=alloca(str_len(host)+1);
      tmp[fmt_str(tmp,host)]=0;
      host=tmp;
    }
    *c='/';
    {
      int tmp=str_chr(host,'%');
      if (host[tmp]) {
	host[tmp]=0;
	scope_id=socket_getifidx(host+tmp+1);
	if (scope_id==0)
	  carp("warning: network interface \"",host+tmp+1,"\" not found.");
      }
    }

    {
      stralloc a={0};
      stralloc_copys(&a,host);
      if (dns_ip6(&ips,&a)==-1)
	die(1,"could not find IP for \"",host,"\"!");
    }

    request=alloca(1300+str_len(host)+3*str_len(c));
    krequest=alloca(1300+str_len(host)+3*str_len(c));
    {
      int i,j;
      i=fmt_str(request,"GET ");
      i+=fmt_urlencoded(request+i,c,str_len(c));
      i+=fmt_str(request+i," HTTP/1.0\r\nHost: ");
      i+=fmt_str(request+i,host);
      i+=fmt_str(request+i,":");
      i+=fmt_ulong(request+i,port);
      i+=fmt_str(request+i,"\r\nUser-Agent: bench/1.0\r\nConnection: ");
      j=i;
      i+=fmt_str(request+i,"close\r\n\r\n");
      rlen=i; request[rlen]=0;
      byte_copy(krequest,rlen,request);
      i=j+fmt_str(krequest+j,"keep-alive\r\n\r\n");
      krlen=i; krequest[krlen]=0;
    }

    hostname=host;

  }

  fds=alloca(c*sizeof(*fds));
  avail=alloca(c*sizeof(*avail));
  expected=alloca(c*sizeof(*expected));
  keepleft=alloca(c*sizeof(*keepleft));
  last.sec.x=23;
  if (!k) K=1;
  for (i=0; i<c; ++i) { fds[i]=-1; avail[i]=1; keepleft[i]=K; }

  taia_now(&first);

  for (done=0; done<n; ) {

    if (t) {
      /* calculate timeout */
      taia_now(&now);
      if (now.sec.x != last.sec.x) {
	byte_copy(&last,sizeof(now),&now);
	byte_copy(&next,sizeof(now),&now);
	next.sec.x += t;
	while ((i=io_timeouted())!=-1) {
	  unsigned long j;
	  char numbuf[FMT_ULONG];
	  numbuf[fmt_ulong(numbuf,i)]=0;
	  carp("timeout on fd ",numbuf,"!");
	  j=(unsigned long)io_getcookie(i);
	  io_close(i);
	  avail[j]=1;
	  fds[j]=-1;
	}
      }
    }

    /* first, fill available connections */
    for (i=0; i<c; ++i)
      if (avail[i]==1 && fds[i]==-1) {
	fds[i]=make_connection(ips.s,port,scope_id,-1);
	if (fds[i]==-1) diesys(1,"socket/connect");
	avail[i]=2;
	if (io_fd(fds[i])==0) diesys(1,"io_fd");
	io_setcookie(fds[i],(void*)i);
//	io_wantread(fds[i]);
	io_wantwrite(fds[i]);
      }

    if (t)
      io_waituntil(next);
    else
      io_wait();

    /* second, see if we can write on a connection */
    while ((i=io_canwrite())!=-1) {
      int j;
      j=(unsigned long)io_getcookie(i);
      if (avail[j]==2) {
	if (make_connection(ips.s,port,scope_id,i)==-1) {
	  ++errors;
	  if (v) write(1,"!",1);
	  io_close(i);
	  avail[j]=1;
	  fds[j]=-1;
	  continue;
	}
      }
      {
	char* towrite;
	int writelen;
	if (mode==REPLAY) {
	  static long lines;
	  char line[1024];
	  char req[2048];
	  int len;
	  int i;
	  char* c;
	  char* host;
	  int hlen;
	  if ((len=buffer_getline(buffer_0,line,sizeof(line)))) {
	    ++lines;
	    if (line[len]!='\n')
	      die(0,"line too long: ",line);
	    line[len]=0;
	    c=line;
	    if (str_start(line,"http://")) c+=7;
	    if (c[0]=='/') {
	      host=hostname;
	      hlen=strlen(hostname);
	    } else {
	      host=c;
	      c+=(hlen=str_chr(c,'/'));
	    }
	    if (!*c)
	      c="/";

	    i=fmt_str(req,"GET ");
	    i+=fmt_urlencoded(req+i,c,str_len(c));
	    i+=fmt_str(req+i," HTTP/1.0\r\nHost: ");
	    byte_copy(req+i,hlen,host); i+=hlen;
	    i+=fmt_str(req+i,":");
	    i+=fmt_ulong(req+i,port);
	    if (cookies) {
	      int j;
	      i+=fmt_str(req+i,"\r\n");
	      j=nextcookie(req+i,sizeof(req)-i-100);
	      if (j!=-1) i+=j; else i-=2;
	    }
	    i+=fmt_str(req+i,"\r\nUser-Agent: bench/1.0\r\nConnection: ");
	    i+=fmt_str(req+i,keepleft[j]>1?"keep-alive\r\n\r\n":"close\r\n\r\n");
	    req[i]=0;
	    towrite=req;
	    writelen=i;
	  } else {
	    n=done;
	    break;
	  }
	} else {
	  if (keepleft[j]>1) {
	    towrite=krequest;
	    writelen=krlen;
	  } else {
	    towrite=request;
	    writelen=rlen;
	  }
	  if (cookies) {
	    int i=writelen-2;
	    int j=nextcookie(towrite+i,900);
	    if (j!=-1) i+=j;
	    i+=fmt_str(towrite+i,"\r\n\r\n");
	    writelen=i;
	  }
	}
	if (io_trywrite(i,towrite,writelen)!=writelen) {
	  ++errors;
	  if (v) write(1,"-",1);
	  io_close(i);
	  avail[j]=1;
	  fds[j]=-1;
	  continue;
	}
      }
      io_dontwantwrite(i);
      io_wantread(i);
      expected[j]=-1;
      if (v) write(1,"+",1);
    }

    /* third, see if we got served */
    while ((i=io_canread())!=-1) {
      char buf[8193];
      int l,j;
      buf[8192]=0;
      j=(unsigned long)io_getcookie(i);
      if ((l=io_tryread(i,buf,sizeof(buf)-1))<=0) {
	if (l==0) { /* EOF.  Mhh. */
	  if (expected[j]>0) {
	    ++errors;
	    if (v) write(1,"-",1);	/* so whine a little */
	  }
	  if (expected[j]==-2)
	    ++done;
	  io_close(i);
	  avail[j]=1;
	  fds[j]=-1;
	} else if (l==-3) {
	  ++errors;
	  if (v) write(1,"!",1);
//	  carpsys("read");
	}
      } else {
	bytes+=l;
	if (v) write(1,".",1);
	/* read something */
	if (expected[j]==-1) {	/* expecting header */
	  int k;
	  /* OK, so this is a very simplistic header parser.  No
	   * buffering.  At all.  We expect the Content-Length header to
	   * come in one piece. */
	  if (l>10 && !memcmp(buf,"HTTP/1.",7)) {
	    if (buf[9]>='0' && buf[9]<='9')
	      r[buf[9]-'0']++;
	    else {
	      write(1,buf,15); write(1,"\n",1);
	    }
	  }
	  expected[j]=-2;
	  if (!done) {
	    for (k=0; k<l; ++k)
	      if (str_start(buf+k,"\nServer: ")) {
		char* tmp=buf+(k+=9);
		for (; k<l; ++k)
		  if (buf[k]=='\r') break;
		k=buf+k-tmp;
		if (k>sizeof(server)-1) k=sizeof(server)-1;
		byte_copy(server,k,tmp);
		server[k]=0;
		break;
	      }
	  }
	  for (k=0; k<l; ++k) {
	    if (str_start(buf+k,"\nContent-Length: ")) {
	      k+=17;
	      if (buf[k+scan_ulonglong(buf+k,(unsigned long long*)expected+j)] != '\r')
		die(1,"parse error in HTTP header!");
	    } else if (str_start(buf+k,"\r\n\r\n"))
	      break;
	  }
	  if (expected[j]>0) {
	    if (l-(k+4)>expected[j])
	      expected[j]=0;
	    else
	      expected[j]-=l-(k+4);
	  }
	} else if (expected[j]==-2) {
	  /* no content-length header, eat everything until EOF */
	} else {
	  if (l>expected[j]) {
	    carp("got more than expected!");
	    expected[j]=0;
	  } else
	    expected[j]-=l;
	}
	if (expected[j]==0) {
	  ++done;	/* one down! */
	  avail[j]=1;
//	  printf("fd %d: keepleft[%d]=%d\n",i,j,keepleft[j]);
	  if (keepleft[j]>1) {
	    --keepleft[j];
	    io_dontwantread(i);
	    io_wantwrite(i);
	    expected[j]=0;
	  } else {
	    keepleft[j]=K;
	    io_close(i);
	    fds[j]=-1;
	  }
	}
      }
    }
  }

  taia_now(&now);
  taia_sub(&now,&now,&first);
  {
    char a[FMT_ULONG];
    char b[FMT_ULONG];
    char C[FMT_ULONG];
    char d[FMT_ULONG];
    char e[FMT_ULONG];
    char f[FMT_ULONG];
    char g[FMT_ULONG];
    char h[FMT_ULONG];
    char i[FMT_ULONG];
    char j[FMT_ULONG];
    unsigned long long l;
    a[fmt_ulong(a,now.sec.x)]=0;
    b[fmt_ulong0(b,(now.nano%1000000000)/100000,4)]=0;
    C[fmt_ulong(C,done)]=0;
    d[fmt_ulonglong(d,errors)]=0;
    e[fmt_ulonglong(e,bytes)]=0;

    /* let's say bytes = 10 MB, time = 1.2 sec.
    * then we want 10*1024*1024/1.2 == 8 MB/sec */
    l = (now.sec.x * 1024) + now.nano/976562;
    if (l) {
      int i;
      l=bytes/l;
      if (report)
	i=fmt_ulong(f,l);
      else {
	i=fmt_humank(f,l*1024);
	i+=fmt_str(f+i,"iB/sec");
      }
      f[i]=0;
    } else
      strcpy(f,"n/a");

    l = (now.sec.x * 1000) + now.nano/1000000;
    l = l ? (done*10000) / l : 0;
    g[fmt_ulong(g,l/10)]=0;
    h[fmt_ulong(h,c)]=0;
    i[fmt_ulong(i,K)]=0;
    j[fmt_ulong(j,kaputt)]=0;

    if (server[0]) msg("Server: ",server);
    if (report) {
      errmsg_iam(0);
      msg("req\terr\tconcur\tkeep\tkbytes\tsec\ttput\tr/s\treset");
      msg(C,"\t",d,"\t",h,"\t",i,"\t",e,"\t",a,".",b,"\t",f,"\t",g,"\t",j);
    } else {
      msg(C," requests, ",d," errors.");
      msg(e," bytes in ",a,".",b," seconds.");
      msg("Throughput: ",f);
      msg("Requests per second: ",g);
      msg("Connection refused/reset by peer: ",j);
    }

    {
      int i;
      for (i=0; i<9; ++i) {
	a[fmt_ulong(a,r[i])]=0;
	b[0]=i+'0'; b[1]=0;
	msg(b,"xx: ",a);
      }
    }
  }

  return 0;
}
Esempio n. 4
0
int main(int argc, char **argv)
{
  int fddata;
	uint32 loc;
	//int v;
	char ipa[4];
	//char ipb[4];
	//ip4_cidr_t *subnets = (ip4_cidr_t *)NULL;
	//unsigned int slen = 0;
	uint32 ipinta = 0U;
	//unsigned int ipintb = 0;
	unsigned short mask;
	uint32 uid = 0;
	uint32  mid = 0;
  int i;
  int j;
  int k;
  char ch;
  unsigned long ttl;
  char ttd[8];
  //uint32 loc;
	unsigned char keyloc[15];
  unsigned long u;
  char ip[4];
	char locp[4];
	//char map[9];
  char type[2];
  char soa[20];
  char buf[4];
  //int namlen = 0;
  umask(022);
  fddata = STDIN_FILENO;
	if (argc != 3) {
    fddata = open_read("data");
		if (fddata == -1) strerr_die2sys(111,FATAL,"unable to open data: ");
		if ( (fdcdb = open_trunc("data.tmp")) == -1) die_datatmp();
	} else {
		fddata = STDIN_FILENO;
		if ( (fdcdb = open_trunc(argv[1])) == -1) die_datatmp();
	}
	
  defaultsoa_init(fddata);

  buffer_init(&b,buffer_unixread,fddata,bspace,sizeof bspace);

  if (cdb_make_start(&cdb,fdcdb) == -1) die_datatmp();

  while (match) {
    ++linenum;
    if (getln(&b,&line,&match,'\n') == -1)
      strerr_die2sys(111,FATAL,"unable to read line: ");

    while (line.len) {
      ch = line.s[line.len - 1];
      if ((ch != ' ') && (ch != '\t') && (ch != '\n')) break;
      --line.len;
    }
    if (!line.len) continue;
    if (line.s[0] == '#') continue;
    if (line.s[0] == '-') continue;
		//write(1,line.s,line.len);
		//write(1,"\n",1);
    j = 1;
    for (i = 0;i < NUMFIELDS;++i) {
      if (j >= line.len) {
				if (!stralloc_copys(&f[i],"")) nomem();
      }
      else {
        k = byte_chr(line.s + j,line.len - j,':');
				if (!stralloc_copyb(&f[i],line.s + j,k)) nomem();
				j += k + 1;
      }
    }

	switch(line.s[0]) {
#ifdef USE_LOCMAPS
	case '%':
		//locparse(&f[0],loc);
		loc = gethash(f[0].s,f[0].len);
		uint32_pack(locp,loc);
		if (!stralloc_0(&f[1])) nomem();
		if (!stralloc_0(&f[2])) nomem();
		ip4_scan(f[1].s,ipa);
		//ip4_scan(f[2].s,ipb);
		scan_ushort(f[2].s,&mask);
		ip4_num(&ipinta,ipa);
		//ip4_num(&ipintb,ipb);
		//if (ipintb<ipinta) nomem();
		//if (ip4_deaggregate(ipinta,ipintb,&subnets,&slen) <= 0) nomem();
		mid = gethash(f[3].s,f[3].len);
		uid = gethash(f[4].s,f[4].len);
		//for (v = 0; v < slen; v++) {
		ipdb_key4build(keyloc,ipinta,(unsigned char )mask&0xff,mid,uid);
		//ipdb_key_from_uint(keyloc,ipinta,(unsigned char )mask&0xff,0,mid,uid);
		cdb_make_add(&cdb,keyloc,15,locp,4);
		//}
		uid = 0;
		//alloc_free(subnets);
		//subnets = NULL;
		//slen = 0;
		byte_zero(ipa,4);ipinta=0; //byte_zero(ipb,4);ipinta=0;ipintb=0;
		break;
#endif
 	case 'Z':
		if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();

		if (!stralloc_0(&f[3])) nomem();
		if (!scan_ulong(f[3].s,&u)) uint32_unpack_big(defaultsoa,&u);
		uint32_pack_big(soa,u);
		if (!stralloc_0(&f[4])) nomem();
		if (!scan_ulong(f[4].s,&u)) uint32_unpack_big(defaultsoa + 4,&u);
		uint32_pack_big(soa + 4,u);
		if (!stralloc_0(&f[5])) nomem();
		if (!scan_ulong(f[5].s,&u)) uint32_unpack_big(defaultsoa + 8,&u);
		uint32_pack_big(soa + 8,u);
		if (!stralloc_0(&f[6])) nomem();
		if (!scan_ulong(f[6].s,&u)) uint32_unpack_big(defaultsoa + 12,&u);
		uint32_pack_big(soa + 12,u);
		if (!stralloc_0(&f[7])) nomem();
		if (!scan_ulong(f[7].s,&u)) uint32_unpack_big(defaultsoa + 16,&u);
		uint32_pack_big(soa + 16,u);

		if (!stralloc_0(&f[8])) nomem();
		if (!scan_ulong(f[8].s,&ttl)) ttl = TTL_NEGATIVE;
		ttdparse(&f[9],ttd);
		loc = gethash(f[10].s,f[10].len);
		mid = gethash(f[11].s,f[11].len);
		uid = gethash(f[12].s,f[12].len);
		rr_addloq(DNS_T_SOA,d1,loc,mid,uid);

		rr_start(DNS_T_SOA,ttl,ttd,loc);
		if (!dns_domain_fromdot(&d2,f[1].s,f[1].len)) nomem();
		rr_addname(d2);
		if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem();
		rr_addname(d2);
		rr_add(soa,20);
		rr_finish(d1);
		break;

	case '.': case '&':
		if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
		if (!stralloc_0(&f[3])) nomem();
		if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_NS;
		ttdparse(&f[4],ttd);
		loc = gethash(f[5].s,f[5].len);
		mid = gethash(f[6].s,f[6].len);
		uid = gethash(f[7].s,f[7].len);

		if (!stralloc_0(&f[1])) nomem();

		if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) {
			if (!stralloc_cats(&f[2],".ns.")) nomem();
			if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem();
		}
		if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem();

		if (line.s[0] == '.') {
			rr_start(DNS_T_SOA,ttl ? TTL_NEGATIVE : 0,ttd,loc);
			rr_addloq(DNS_T_SOA,d1,loc,mid,uid);
			rr_addname(d2);
			rr_add("\12hostmaster",11);
			rr_addname(d1);
			rr_add(defaultsoa,20);
			rr_finish(d1);
		}

		rr_start(DNS_T_NS,ttl,ttd,loc);
		rr_addname(d2);
		rr_addloq(DNS_T_NS,d2,loc,mid,uid);
		rr_finish(d1);

		if (ip4_scan(f[1].s,ip)) {
	  	rr_start(DNS_T_A,ttl,ttd,loc);
			rr_addloq(DNS_T_A,d2,loc,mid,uid);
			rr_add(ip,4);
			rr_finish(d2);
		}

		break;

	case '+': case '=':
		if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
		if (!stralloc_0(&f[2])) nomem();
		if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE;
		ttdparse(&f[3],ttd);
		loc = gethash(f[4].s,f[4].len);
		mid = gethash(f[5].s,f[5].len);
		uid = gethash(f[6].s,f[6].len);

		if (!stralloc_0(&f[1])) nomem();

		if (ip4_scan(f[1].s,ip)) {
			rr_addloq(DNS_T_A,d1,loc,mid,uid);
			rr_start(DNS_T_A,ttl,ttd,loc);
			//dbger("+addloq:d=%s,loc=%u,uid=%u,mid=%u",d1,loc,uid,mid);
			rr_add(ip,4);
			rr_finish(d1);

			if (line.s[0] == '=') {
				rr_addloq(DNS_T_PTR,d1,loc,mid,uid); //??????????????????/ TODO: checkthis
				dns_name4_domain(dptr,ip);
				rr_start(DNS_T_PTR,ttl,ttd,loc);
				rr_addname(d1);
				rr_finish(dptr);
			}
		}
		break;

	case '@':
		if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
		if (!stralloc_0(&f[4])) nomem();
		if (!scan_ulong(f[4].s,&ttl)) ttl = TTL_POSITIVE;
		ttdparse(&f[5],ttd);
		loc = gethash(f[6].s,f[6].len);
		mid = gethash(f[7].s,f[7].len);
		uid = gethash(f[8].s,f[8].len);

		if (!stralloc_0(&f[1])) nomem();

		if (byte_chr(f[2].s,f[2].len,'.') >= f[2].len) {
			if (!stralloc_cats(&f[2],".mx.")) nomem();
			if (!stralloc_catb(&f[2],f[0].s,f[0].len)) nomem();
		}
		if (!dns_domain_fromdot(&d2,f[2].s,f[2].len)) nomem();

		if (!stralloc_0(&f[3])) nomem();
		if (!scan_ulong(f[3].s,&u)) u = 0;

		rr_addloq(DNS_T_MX,d1,loc,mid,uid);
		rr_start(DNS_T_MX,ttl,ttd,loc);
		uint16_pack_big(buf,u);
		rr_add(buf,2);
		rr_addname(d2);
		rr_finish(d1);

		if (ip4_scan(f[1].s,ip)) {
			rr_addloq(DNS_T_A,d2,loc,mid,uid);
			rr_start(DNS_T_A,ttl,ttd,loc);
			rr_add(ip,4);
			rr_finish(d2);
		}
		break;

	case '^': case 'C':
		if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
		if (!dns_domain_fromdot(&d2,f[1].s,f[1].len)) nomem();
		if (!stralloc_0(&f[2])) nomem();
		if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE;
		ttdparse(&f[3],ttd);
		loc = gethash(f[4].s,f[4].len);
		mid = gethash(f[5].s,f[5].len);
		uid = gethash(f[6].s,f[6].len);

		if (line.s[0] == 'C') {
			//rr_addloq(DNS_T_CNAME,d1,loc,mid,uid);
			//dbger("add loq for cname!");
			rr_addloq(DNS_T_A,d1,loc,mid,uid);
			rr_addloq(DNS_T_CNAME,d1,loc,mid,uid);
			rr_start(DNS_T_CNAME,ttl,ttd,loc);
		} else {
			rr_addloq(DNS_T_PTR,d1,loc,mid,uid);
			rr_start(DNS_T_PTR,ttl,ttd,loc);
		}
		rr_addname(d2);
		rr_finish(d1);
		break;

	case '\'':
		if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
		if (!stralloc_0(&f[2])) nomem();
		if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE;
		ttdparse(&f[3],ttd);
		loc = gethash(f[4].s,f[4].len);
		mid = gethash(f[5].s,f[5].len);
		uid = gethash(f[6].s,f[6].len);

		rr_addloq(DNS_T_TXT,d1,loc,mid,uid);
		rr_start(DNS_T_TXT,ttl,ttd,loc);
		txtparse(&f[1]);
		i = 0;
		while (i < f[1].len) {
			k = f[1].len - i;
			if (k > 127) k = 127;
			ch = k;
			rr_add(&ch,1);
			rr_add(f[1].s + i,k);
			i += k;
		}

		rr_finish(d1);
		break;

	case ':':
		if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
		if (!stralloc_0(&f[3])) nomem();
		if (!scan_ulong(f[3].s,&ttl)) ttl = TTL_POSITIVE;
		ttdparse(&f[4],ttd);
		loc = gethash(f[5].s,f[5].len);
		mid = gethash(f[6].s,f[6].len);
		uid = gethash(f[7].s,f[7].len);

		if (!stralloc_0(&f[1])) nomem();
		scan_ulong(f[1].s,&u);
		uint16_pack_big(type,u);
		if (byte_equal(type,2,DNS_T_AXFR))
			syntaxerror(": type AXFR prohibited");
		if (byte_equal(type,2,"\0\0"))
			syntaxerror(": type 0 prohibited");
		if (byte_equal(type,2,DNS_T_SOA))
			syntaxerror(": type SOA prohibited");
		if (byte_equal(type,2,DNS_T_NS))
			syntaxerror(": type NS prohibited");
		if (byte_equal(type,2,DNS_T_CNAME))
			syntaxerror(": type CNAME prohibited");
		if (byte_equal(type,2,DNS_T_PTR))
			syntaxerror(": type PTR prohibited");
		if (byte_equal(type,2,DNS_T_MX))
			syntaxerror(": type MX prohibited");
		txtparse(&f[2]);
		rr_addloq(type,d1,loc,mid,uid);
		rr_start(type,ttl,ttd,loc);
		rr_add(f[2].s,f[2].len);
		rr_finish(d1);
		break;
	default:
		dienow("error here: %s\n", line.s);
		syntaxerror(": unrecognized leading character");
}
}

  if (cdb_make_finish(&cdb) == -1) die_datatmp();
  if (fsync(fdcdb) == -1) die_datatmp();
  if (close(fdcdb) == -1) die_datatmp(); /* NFS stupidity */
	if (argc  == 3) {
		if (rename(argv[1],argv[2]) == -1) strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
	} else {
		if (rename("data.tmp","data.cdb") == -1) strerr_die2sys(111,FATAL,"unable to move data.tmp to data.cdb: ");
	}

  _exit(0);
}
Esempio n. 5
0
int
main(int argc, char* argv[]) {
  int s;
  uint16 port = 2342;
  uint32 scope_id = 0;
  char ip[16];
  char buf[8192];
  int i;
  struct pollfd p[2];

  if(argc < 3) {
  usage:
    __write2("usage: client ip port\n\nexample: dump -0 -f - | client 10.0.0.149 8000\n");
    return 0;
  }
  if(argv[1][i = scan_ip6if(argv[1], ip, &scope_id)]) {
    __write2("client: error: invalid ip address!\n");
    goto usage;
  }
  if(argv[2][scan_ushort(argv[2], &port)]) {
    __write2("client: error: invalid port number!\n");
    goto usage;
  }
  if(byte_equal(ip, 12, V4mappedprefix)) {
    s = socket_tcp4b();
    if(s == -1)
      panic("client: error: socket() failed");
    if(socket_connect4(s, ip + 12, port) == -1)
      panic("client: error: connect() failed");
  } else {
    s = socket_tcp6b();
    if(s == -1)
      panic("client: error: socket() failed");
    if(socket_connect6(s, ip, port, scope_id) == -1)
      panic("client: error: connect() failed");
  }
  ndelay_off(s);
  p[0].fd = 0;
  p[0].events = POLLIN;
  p[1].fd = s;
  p[1].events = POLLIN;
  while(poll(p, 2, 5000)) {
    if(p[0].revents) {
      int j;
      if(p[0].revents & POLLERR)
        panic("client: error: poll() signals POLLERR\n");
      i = read(0, buf, sizeof(buf));
      if(i == 0) {
        shutdown(s, SHUT_WR);
        blockingcopy(s, 1);
      }
      for(j = 0; j < i;) {
        int k = write(s, buf + j, i - j);
        if(k == -1)
          panic("client: error: write() failed");
        if(k == 0)
          panic("client: error: short write!\n");
        j += k;
      }
    }
    if(p[1].revents) {
      int j;
      if(p[1].revents & POLLERR)
        panic("client: error: poll() signals POLLERR\n");
      i = read(s, buf, sizeof(buf));
      if(i == 0) {
        shutdown(1, SHUT_WR);
        blockingcopy(0, s);
      }
      for(j = 0; j < i;) {
        int k = write(1, buf + j, i - j);
        if(k == -1)
          panic("client: error: write() failed");
        if(k == 0)
          panic("client: error: short write!\n");
        j += k;
      }
    }
  }
  return 0;
}
Esempio n. 6
0
int main(int argc,char* argv[]) {
  unsigned long count=1000;
  unsigned long interval=10;
  unsigned long sample=5;
  int keepalive=0;
  char ip[16];
  uint16 port=80;
  uint32 scope_id=0;
  stralloc ips={0};
  int s;
  char* request;
  int rlen;

  signal(SIGPIPE,SIG_IGN);

  if (!geteuid()) {
    struct rlimit rl;
    long l;
#ifdef RLIMIT_NPROC
    rl.rlim_cur=RLIM_INFINITY; rl.rlim_max=RLIM_INFINITY;
    setrlimit(RLIMIT_NPROC,&rl);
#endif
    for (l=0; l<20000; l+=500) {
      rl.rlim_cur=l; rl.rlim_max=l;
      if (setrlimit(RLIMIT_NOFILE,&rl)==-1) break;
    }
  }

  for (;;) {
    int i;
    int c=getopt(argc,argv,"c:i:s:kb");
    if (c==-1) break;
    switch (c) {
    case 'k':
      keepalive=1;
      break;
    case 'i':
      i=scan_ulong(optarg,&interval);
      if (i==0 || optarg[i]) {
	buffer_puts(buffer_2,"httpbench: warning: could not parse interval: ");
	buffer_puts(buffer_2,optarg+i+1);
	buffer_putsflush(buffer_2,"\n");
      }
      break;
    case 'c':
      i=scan_ulong(optarg,&count);
      if (i==0 || optarg[i]) {
	buffer_puts(buffer_2,"httpbench: warning: could not parse count: ");
	buffer_puts(buffer_2,optarg+i+1);
	buffer_putsflush(buffer_2,"\n");
      }
      break;
    case 's':
      i=scan_ulong(optarg,&sample);
      if (i==0 || optarg[i]) {
	buffer_puts(buffer_2,"httpbench: warning: could not parse sample size: ");
	buffer_puts(buffer_2,optarg+i+1);
	buffer_putsflush(buffer_2,"\n");
      }
      break;
    case 'b':
      bindport=10000;
      break;
    case '?':
usage:
      buffer_putsflush(buffer_2,
		  "usage: httpbench [-hb] [-c count] [-i interval] [-s sample] url\n"
		  "\n"
		  "\t-h\tprint this help\n"
		  "\t-c n\topen n connections total (default: 1000)\n"
		  "\t-i n\tevery n connections, measure the latency (default: 10)\n"
		  "\t-s n\tlatency == average of time to fetch an URL n times (default: 5)\n"
		  "\t-k\tenable HTTP keep-alive\n"
		  "\t-b\tbind the sockets ourselves, so the OS doesn't choose the ports\n"
		  "Setting the number of connections to 1 measures the throughput\n"
		  "instead of the latency (give URL to a large file).\n");
      return 0;
    }
  }

  if (!argv[optind]) goto usage;
  if (byte_diff(argv[optind],7,"http://")) goto usage;
  {
    char* host=argv[optind]+7;
    int colon=str_chr(host,':');
    int slash=str_chr(host,'/');
    char* c;
    if (host[0]=='[') {	/* ipv6 IP notation */
      int tmp;
      ++host;
      --colon; --slash;
      tmp=str_chr(host,']');
      if (host[tmp]==']') host[tmp]=0;
      if (host[tmp+1]==':') colon=tmp+1;
      if (colon<tmp+1) colon=tmp+1+str_len(host+tmp+1);
    }
    if (colon<slash) {
      host[colon]=0;
      c=host+colon+1;
      if (c[scan_ushort(c,&port)]!='/') goto usage;
      *c=0;
    }
    host[colon]=0;
    c=host+slash;
    *c=0;
    {
      char* tmp=alloca(str_len(host)+1);
      tmp[fmt_str(tmp,host)]=0;
      host=tmp;
    }
    *c='/';
    {
      int tmp=str_chr(host,'%');
      if (host[tmp]) {
	host[tmp]=0;
	scope_id=socket_getifidx(host+tmp+1);
	if (scope_id==0) {
	  buffer_puts(buffer_2,"httpbench: warning: network interface ");
	  buffer_puts(buffer_2,host+tmp+1);
	  buffer_putsflush(buffer_2," not found.\n");
	}
      }
    }

    {
      stralloc a={0};
      stralloc_copys(&a,host);
      if (dns_ip6(&ips,&a)==-1) {
	buffer_puts(buffer_2,"httpbench: could not resolve IP: ");
	buffer_puts(buffer_2,host);
	buffer_putnlflush(buffer_2);
	return 1;
      }
    }

    request=malloc(300+str_len(host)+str_len(c)*3);
    if (!request) panic("malloc");
    {
      int i;
      i=fmt_str(request,"GET ");
      i+=fmt_urlencoded(request+i,c,str_len(c));
      i+=fmt_str(request+i," HTTP/1.0\r\nHost: ");
      i+=fmt_str(request+i,host);
      i+=fmt_str(request+i,":");
      i+=fmt_ulong(request+i,port);
      i+=fmt_str(request+i,"\r\nUser-Agent: httpbench/1.0\r\nConnection: ");
      i+=fmt_str(request+i,keepalive?"keep-alive":"close");
      i+=fmt_str(request+i,"\r\n\r\n");
      rlen=i; request[rlen]=0;
    }

  }

  {
    int i;
    s=-1;
    for (i=0; i+16<=ips.len; i+=16) {
      char buf[IP6_FMT];
      int v6=byte_diff(ips.s+i,12,V4mappedprefix);
      buffer_puts(buffer_1,"connecting to ");
      buffer_put(buffer_1,buf,
		 v6?
		 fmt_ip6(buf,ips.s+i):
		 fmt_ip4(buf,ips.s+i+12));
      buffer_puts(buffer_1," port ");
      buffer_putulong(buffer_1,port);
      buffer_putnlflush(buffer_1);
      s=make_connection(ips.s+i,port,scope_id);
      if (s!=-1) {
	byte_copy(ip,16,ips.s+i);
	break;
      }
    }
    if (s==-1)
      return 1;
  }
  if (write(s,request,rlen)!=rlen) panic("write");
  if (readanswer(s,count==1)==-1) exit(1);
  close(s);
  if (count==1)
    return 0;

  {
    long i;
    long j;
    long err=0;
    int *socks;
    socks=malloc(sizeof(int)*count);
    if (!socks) panic("malloc");
    for (i=j=0; i<count; ++i) {
      struct timeval a,b;
      long d;
      if (j==0) {
	int k,s=0;
	long x=0,y=0;
	for (k=0; k<sample; ++k) {
	  if (!keepalive || !k) {
	    gettimeofday(&a,0);
	    s=make_connection(ip,port,scope_id);
	    if (s==-1)
	      panic("make_connection");
	    gettimeofday(&b,0);
	    d=(b.tv_sec-a.tv_sec)*1000000;
	    d=d+b.tv_usec-a.tv_usec;
	    x+=d;
	  }
	  gettimeofday(&a,0);
	  write(s,request,rlen);
	  if (readanswer(s,0)==-1) {
	    ++err;
	    keepalive=0;
	  }
	  gettimeofday(&b,0);
	  d=(b.tv_sec-a.tv_sec)*1000000;
	  d=d+b.tv_usec-a.tv_usec;
	  y+=d;
	  if (!keepalive) close(s);
	}
	if (keepalive) close(s);
	buffer_puts(buffer_1,"sample ");
	buffer_putulong(buffer_1,x);
	buffer_puts(buffer_1," ");
	buffer_putulong(buffer_1,y/sample);
	buffer_putnlflush(buffer_1);
      }
      ++j; if (j==interval) j=0;

      gettimeofday(&a,0);
      socks[i]=make_connection(ip,port,scope_id);
      if (socks[i]==-1)
	panic("make_connection");
      gettimeofday(&b,0);
      d=(b.tv_sec-a.tv_sec)*1000000;
      d=d+b.tv_usec-a.tv_usec;
      buffer_puts(buffer_1,"clat ");
      buffer_putulong(buffer_1,d);
      buffer_putnlflush(buffer_1);
    }
  }
  buffer_flush(buffer_1);
  return 0;
}
Esempio n. 7
0
int main(int argc,char* argv[]) {
  int s,t;
  uint16 port=2342;
  uint32 scope_id=0;
  char ip[16];
  char buf[8192];
  int i;
  struct pollfd p[2];

  if (argc<3) {
usage:
    __write2("usage: server ip port\n\nexample: server 0 8000 | restore x -f -\n");
    return 0;
  }
  if (!strcmp(argv[1],"0"))
    byte_zero(ip,16);
  else
    if (argv[1][i=scan_ip6if(argv[1],ip,&scope_id)]) {
      __write2("server: error: invalid ip address!\n");
      goto usage;
    }
  if (argv[2][scan_ushort(argv[2],&port)]) {
    __write2("server: error: invalid port number!\n");
    goto usage;
  }
  if (byte_equal(ip,12,V4mappedprefix)) {
    s=socket_tcp4b();
    if (s==-1) panic("server: error: socket() failed");
    if (socket_bind4_reuse(s,ip+12,port)==-1) panic("server: error: bind() failed");
    if (socket_listen(s,1)==-1) panic("server: error: listen() failed");
    ndelay_off(s);
    if ((t=socket_accept4(s,0,0))==-1) panic("server: error: accept() failed");
  } else {
    s=socket_tcp6b();
    if (s==-1) panic("server: error: socket() failed");
    if (socket_bind6_reuse(s,ip,port,scope_id)==-1) panic("server: error: bind() failed");
    if (socket_listen(s,1)==-1) panic("server: error: listen() failed");
    ndelay_off(s);
    if ((t=socket_accept6(s,0,0,0))==-1) panic("server: error: accept() failed");
  }
  close(s);
  p[0].fd=0; p[0].events=POLLIN;
  p[1].fd=t; p[1].events=POLLIN;
  while (poll(p,2,5000)) {
    if (p[0].revents) {
      int j;
      if (p[0].revents&POLLERR)
	panic("server: error: poll() signals POLLERR\n");
      i=read(0,buf,sizeof(buf));
      if (i==0) { shutdown(t,SHUT_WR); blockingcopy(t,1); }
      for (j=0; j<i; ) {
	int k=write(t,buf+j,i-j);
	if (k==-1) panic("server: error: write() failed");
	if (k==0) panic("server: error: short write!\n");
	j+=k;
      }
    }
    if (p[1].revents) {
      int j;
      if (p[1].revents&POLLERR)
	panic("server: error: poll() signals POLLERR\n");
      i=read(t,buf,sizeof(buf));
      if (i==0) { shutdown(1,SHUT_WR); blockingcopy(0,t); }
      for (j=0; j<i; ) {
	int k=write(1,buf+j,i-j);
	if (k==-1) panic("server: error: write() failed");
	if (k==0) panic("server: error: short write!\n");
	j+=k;
      }
    }
  }
  return 0;
}
Esempio n. 8
0
int
main(int argc, char* argv[]) {
  int s = socket_tcp6();
  uint32 scope_id;
  char ip[16];
  uint16 port;
  char hisip[16];
  uint16 hisport;
  uint32 hisscope_id;
  static char seed[128];
  static stralloc fqdn;
  static stralloc out;

  if(argc != 4) {
  usage:
    buffer_putsflush(buffer_2,
                     "usage: proxy myip myport hisip hisport\n"
                     "\n"
                     "e.g.: proxy 0 119 news.fu-berlin.de 119\n");
    return 0;
  }

  if(argv[1][scan_ip6if(argv[1], ip, &scope_id)]) {
    if(str_equal(argv[1], "0")) {
      byte_zero(ip, 16);
      scope_id = 0;
    } else
      goto usage;
  }
  if(argv[2][scan_ushort(argv[2], &port)])
    goto usage;
  if(argv[3][scan_ip6if(argv[3], hisip, &hisscope_id)]) {
    dns_random_init(seed);
    if(!stralloc_copys(&fqdn, argv[3]))
      goto nomem;
    if(dns_ip4(&out, &fqdn) == -1) {
      buffer_puts(buffer_2, "unable to find IP address for ");
      buffer_puts(buffer_2, argv[3]);
      buffer_puts(buffer_2, ": ");
      buffer_puterror(buffer_2);
      buffer_putnlflush(buffer_2);
      return 111;
    }
  } else if(!stralloc_catb(&out, hisip, 16)) {
  nomem:
    buffer_putsflush(buffer_2, "out of memory\n");
    return 111;
  }
  if(argv[4][scan_ushort(argv[4], &hisport)])
    goto usage;

  if(socket_bind6_reuse(s, ip, port, scope_id) == -1) {
    buffer_puts(buffer_2, "socket_bind6_reuse: ");
    buffer_puterror(buffer_2);
    buffer_putnlflush(buffer_2);
    return 111;
  }
  if(socket_listen(s, 16) == -1) {
    buffer_puts(buffer_2, "socket_listen: ");
    buffer_puterror(buffer_2);
    buffer_putnlflush(buffer_2);
    return 111;
  }
  if(!io_fd(s)) {
    buffer_puts(buffer_2, "io_fd: ");
    buffer_puterror(buffer_2);
    buffer_putnlflush(buffer_2);
    return 111;
  }
  io_wantread(s);
  for(;;) {
    int64 i;
    io_wait();
    while((i = io_canread()) != -1) {
      if(i == s) {
        /* the read event is on the server socket */
        /* that means it's an incoming connection */
        int n;
        while((n = socket_accept6(s, ip, &port, &scope_id)) != -1) {
          int x = socket_tcp6();
          if(x == -1) {
            buffer_puts(buffer_2, "socket_tcp6 failed: ");
          fail:
            buffer_puterror(buffer_2);
            buffer_putnlflush(buffer_2);
            io_close(n);
          } else {
            struct state* s = malloc(sizeof(struct state));
            if(!s)
              goto closefail;
            s->a = n;
            s->b = x;
            s->connected = 0;
            s->done = s->todo = 0;
            s->dir = UNDECIDED;
            io_nonblock(x);
            socket_connect6(x, out.s, hisport, hisscope_id);
            if(!io_fd(x) || !io_fd(n)) {
              buffer_puts(buffer_2, "io_fd failed: ");
            closefail:
              free(s);
              io_close(x);
              goto fail;
            }
            io_setcookie(x, s);
            io_setcookie(n, s);
            io_wantwrite(x);
          }
        }
        if(errno != EAGAIN) {
          buffer_puts(buffer_2, "socket_accept6 failed: ");
          buffer_puterror(buffer_2);
          buffer_putnlflush(buffer_2);
        }
      } else {
        /* read event on an established connection */
        struct state* s = io_getcookie(i);
        int l = io_tryread(i, s->buf, sizeof(s->buf));
        if(l == -1) {
          buffer_puts(buffer_2, "io_tryread(");
          buffer_putulong(buffer_2, i);
          buffer_puts(buffer_2, "): ");
          buffer_puterror(buffer_2);
          buffer_putnlflush(buffer_2);
          io_close(s->a);
          io_close(s->b);
        } else if(l == 0) {
          buffer_puts(buffer_2, "eof on fd #");
          buffer_putulong(buffer_2, i);
          buffer_putnlflush(buffer_2);
          io_close(i);
        } else {
          int r;
          switch(r = io_trywrite(i, s->buf, l)) {
            case -1:
              buffer_puts(buffer_2, "io_tryread(");
              buffer_putulong(buffer_2, i);
              buffer_puts(buffer_2, "): ");
              buffer_puterror(buffer_2);
              buffer_putnlflush(buffer_2);
              io_close(i);
              break;
            case 0:
              buffer_puts(buffer_2, "write eof on fd #");
              buffer_putulong(buffer_2, i);
              buffer_putnlflush(buffer_2);
              io_close(i);
            default:
              if(r != l) {
                buffer_puts(buffer_2, "short write on fd #");
                buffer_putulong(buffer_2, i);
                buffer_puts(buffer_2, ": wrote ");
                buffer_putulong(buffer_2, r);
                buffer_puts(buffer_2, ", wanted to write ");
                buffer_putulong(buffer_2, l);
                buffer_putsflush(buffer_2, ").\n");
              }
          }
        }
      }
    }
  }
  return 0;
}