9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* Re: [9fans] fs error msg: didn't like (1460 274) byte message
@ 2002-09-24 23:42 Russ Cox
  2002-09-25 11:45 ` Axel Belinfante
  2002-09-25 18:19 ` Axel Belinfante
  0 siblings, 2 replies; 10+ messages in thread
From: Russ Cox @ 2002-09-24 23:42 UTC (permalink / raw)
  To: 9fans

Oops.  I wonder why we never noticed that before.
The problem is that TCP lost the race, and a 1734 byte
message got turned into a 1460 and a 2764.  Since IL
preserves message delimiters, the file server choked
on the two halves.  Here's a new aux/trampoline.  Run
aux/trampoline -9 and it should do the right thing
as far as putting the 9P messages back together before
passing them along.

Let me know if it works, and I'll put it on sources.
Russ


#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ndb.h>
#include <fcall.h>

enum
{
	Maxpath=	128,
};

typedef struct Endpoints Endpoints;
struct Endpoints
{
	char 	*net;
	char	*lsys;
	char	*lserv;
	char	*rsys;
	char	*rserv;
};

void		xfer(int, int);
void		xfer9p(int, int);
Endpoints*	getendpoints(char*);
void		freeendpoints(Endpoints*);
char*		iptomac(char*, char*);
int		macok(char*);

void
main(int argc, char **argv)
{
	int fd;
	int checkmac = 0;
	Endpoints *ep;
	char *mac;
	void (*x)(int, int);

	x = xfer;
	ARGBEGIN{
	case 'm':
		checkmac = 1;
		break;
	case '9':
		x = xfer9p;
		break;
	}ARGEND;

	if(argc < 1){
		fprint(2, "usage: %s dialstring\n", argv0);
		exits("usage");
	}
	if(checkmac && argc > 1){
		ep = getendpoints(argv[1]);
		mac = iptomac(ep->rsys, ep->net);
		if(!macok(mac)){
			syslog(0, "trampoline", "badmac %s from %s!%s for %s!%s on %s",
				mac, ep->rsys, ep->rserv, ep->lsys, ep->lserv, ep->net);
			exits("bad mac");
		}
	}
	fd = dial(argv[0], 0, 0, 0);
	if(fd < 0){
		fprint(2, "%s: dialing %s: %r\n", argv0, argv[0]);
		exits("dial");
	}
	rfork(RFNOTEG);
	switch(fork()){
	case -1:
		fprint(2, "%s: fork: %r\n", argv0);
		exits("dial");
	case 0:
		(*x)(0, fd);
		break;
	default:
		(*x)(fd, 1);
		break;
	}
	postnote(PNGROUP, getpid(), "die yankee pig dog");
	exits(0);
}

void
xfer(int from, int to)
{
	char buf[12*1024];
	int n;

	while((n = read(from, buf, sizeof buf)) > 0)
		if(write(to, buf, n) < 0)
			break;
}

void
xfer9p(int from, int to)
{
	char *buf;
	uint nbuf;
	int n;

	nbuf = 256;
	buf = malloc(nbuf);
	if(buf == nil)
		sysfatal("xfer: malloc %ud: %r", nbuf);

	for(;;){
		if(readn(from, buf, 4) != 4)
			break;
		n = GBIT32(buf);
		if(4+n > nbuf){
			nbuf = 4+n+8192;
			buf = realloc(buf, nbuf);
			if(buf == nil)
				sysfatal("xfer: realloc %ud: %r", nbuf);
		}
		if(readn(from, buf+4, n) != n)
			break;
		if(write(to, buf, 4+n) != 4+n)
			break;
	}
}

void
getendpoint(char *dir, char *file, char **sysp, char **servp)
{
	int fd, n;
	char buf[Maxpath];
	char *sys, *serv;

	sys = serv = 0;

	snprint(buf, sizeof buf, "%s/%s", dir, file);
	fd = open(buf, OREAD);
	if(fd >= 0){
		n = read(fd, buf, sizeof(buf)-1);
		if(n>0){
			buf[n-1] = 0;
			serv = strchr(buf, '!');
			if(serv){
				*serv++ = 0;
				serv = strdup(serv);
			}
			sys = strdup(buf);
		}
		close(fd);
	}
	if(serv == 0)
		serv = strdup("unknown");
	if(sys == 0)
		sys = strdup("unknown");
	*servp = serv;
	*sysp = sys;
}

Endpoints *
getendpoints(char *dir)
{
	Endpoints *ep;
	char *p;

	ep = malloc(sizeof(*ep));
	ep->net = strdup(dir);
	p = strchr(ep->net+1, '/');
	if(p == nil){
		free(ep->net);
		ep->net = "/net";
	} else
		*p = 0;
	getendpoint(dir, "local", &ep->lsys, &ep->lserv);
	getendpoint(dir, "remote", &ep->rsys, &ep->rserv);
	return ep;
}

void
freeendpoints(Endpoints *ep)
{
	free(ep->lsys);
	free(ep->rsys);
	free(ep->lserv);
	free(ep->rserv);
	free(ep);
}

char*
iptomac(char *ip, char *net)
{
	char file[Maxpath];
	Biobuf *b;
	char *p;
	char *f[5];

	snprint(file, sizeof(file), "%s/arp", net);
	b = Bopen(file, OREAD);
	if(b == nil)
		return nil;
	while((p = Brdline(b, '\n')) != nil){
		p[Blinelen(b)-1] = 0;
		if(tokenize(p, f, nelem(f)) < 4)
			continue;
		if(strcmp(f[1], "OK") == 0
		&& strcmp(f[2], ip) == 0){
			p = strdup(f[3]);
			Bterm(b);
			return p;
		}
	}
	Bterm(b);
	return nil;
}

int
macok(char *mac)
{
	Ndbtuple *tp;
	char buf[Ndbvlen];

	if(mac == nil)
		return 0;
	tp = csgetval("/net", "ether", mac, "trampok", buf);
	if(tp == nil)
		return 0;
	ndbfree(tp);
	return 1;
}



^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: [9fans] fs error msg: didn't like (1460 274) byte message
@ 2002-09-25 21:30 Russ Cox
  2002-09-26  8:49 ` Axel Belinfante
  0 siblings, 1 reply; 10+ messages in thread
From: Russ Cox @ 2002-09-25 21:30 UTC (permalink / raw)
  To: 9fans

this works just fine for me.
does it work for you?  if not, what
are the hex bytes of the weird 152-byte
message.  how do you know it's 152 bytes
when n == -104?

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ndb.h>
#include <fcall.h>

enum
{
	Maxpath=	128,
};

typedef struct Endpoints Endpoints;
struct Endpoints
{
	char 	*net;
	char	*lsys;
	char	*lserv;
	char	*rsys;
	char	*rserv;
};

void		xfer(int, int);
void		xfer9p(int, int);
Endpoints*	getendpoints(char*);
void		freeendpoints(Endpoints*);
char*		iptomac(char*, char*);
int		macok(char*);

void
main(int argc, char **argv)
{
	int fd;
	int checkmac = 0;
	Endpoints *ep;
	char *mac;
	void (*x)(int, int);

	x = xfer;
	ARGBEGIN{
	case 'm':
		checkmac = 1;
		break;
	case '9':
		x = xfer9p;
		break;
	}ARGEND;

	if(argc < 1){
		fprint(2, "usage: %s dialstring\n", argv0);
		exits("usage");
	}
	if(checkmac && argc > 1){
		ep = getendpoints(argv[1]);
		mac = iptomac(ep->rsys, ep->net);
		if(!macok(mac)){
			syslog(0, "trampoline", "badmac %s from %s!%s for %s!%s on %s",
				mac, ep->rsys, ep->rserv, ep->lsys, ep->lserv, ep->net);
			exits("bad mac");
		}
	}
	fd = dial(argv[0], 0, 0, 0);
	if(fd < 0){
		fprint(2, "%s: dialing %s: %r\n", argv0, argv[0]);
		exits("dial");
	}
	rfork(RFNOTEG);
	switch(fork()){
	case -1:
		fprint(2, "%s: fork: %r\n", argv0);
		exits("dial");
	case 0:
		(*x)(0, fd);
		break;
	default:
		(*x)(fd, 1);
		break;
	}
	postnote(PNGROUP, getpid(), "die yankee pig dog");
	exits(0);
}

void
xfer(int from, int to)
{
	char buf[12*1024];
	int n;

	while((n = read(from, buf, sizeof buf)) > 0)
		if(write(to, buf, n) < 0)
			break;
}

void
xfer9p(int from, int to)
{
	uchar *buf;
	uint nbuf;
	int n;

	nbuf = 256;
	buf = malloc(nbuf);
	if(buf == nil)
		sysfatal("xfer: malloc %ud: %r", nbuf);

	for(;;){
		if(readn(from, buf, 4) != 4)
			break;
		n = GBIT32(buf);
		if(n > nbuf){
			nbuf = n+8192;
			buf = realloc(buf, nbuf);
			if(buf == nil)
				sysfatal("xfer: realloc %ud: %r", nbuf);
		}
		if(readn(from, buf+4, n-4) != n-4)
			break;
		if(write(to, buf, n) != n){
			sysfatal("oops: %r");
			break;
		}
	}
}

void
getendpoint(char *dir, char *file, char **sysp, char **servp)
{
	int fd, n;
	char buf[Maxpath];
	char *sys, *serv;

	sys = serv = 0;

	snprint(buf, sizeof buf, "%s/%s", dir, file);
	fd = open(buf, OREAD);
	if(fd >= 0){
		n = read(fd, buf, sizeof(buf)-1);
		if(n>0){
			buf[n-1] = 0;
			serv = strchr(buf, '!');
			if(serv){
				*serv++ = 0;
				serv = strdup(serv);
			}
			sys = strdup(buf);
		}
		close(fd);
	}
	if(serv == 0)
		serv = strdup("unknown");
	if(sys == 0)
		sys = strdup("unknown");
	*servp = serv;
	*sysp = sys;
}

Endpoints *
getendpoints(char *dir)
{
	Endpoints *ep;
	char *p;

	ep = malloc(sizeof(*ep));
	ep->net = strdup(dir);
	p = strchr(ep->net+1, '/');
	if(p == nil){
		free(ep->net);
		ep->net = "/net";
	} else
		*p = 0;
	getendpoint(dir, "local", &ep->lsys, &ep->lserv);
	getendpoint(dir, "remote", &ep->rsys, &ep->rserv);
	return ep;
}

void
freeendpoints(Endpoints *ep)
{
	free(ep->lsys);
	free(ep->rsys);
	free(ep->lserv);
	free(ep->rserv);
	free(ep);
}

char*
iptomac(char *ip, char *net)
{
	char file[Maxpath];
	Biobuf *b;
	char *p;
	char *f[5];

	snprint(file, sizeof(file), "%s/arp", net);
	b = Bopen(file, OREAD);
	if(b == nil)
		return nil;
	while((p = Brdline(b, '\n')) != nil){
		p[Blinelen(b)-1] = 0;
		if(tokenize(p, f, nelem(f)) < 4)
			continue;
		if(strcmp(f[1], "OK") == 0
		&& strcmp(f[2], ip) == 0){
			p = strdup(f[3]);
			Bterm(b);
			return p;
		}
	}
	Bterm(b);
	return nil;
}

int
macok(char *mac)
{
	Ndbtuple *tp;
	char buf[Ndbvlen];

	if(mac == nil)
		return 0;
	tp = csgetval("/net", "ether", mac, "trampok", buf);
	if(tp == nil)
		return 0;
	ndbfree(tp);
	return 1;
}



^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: [9fans] fs error msg: didn't like (1460 274) byte message
@ 2002-09-25 21:21 Russ Cox
  0 siblings, 0 replies; 10+ messages in thread
From: Russ Cox @ 2002-09-25 21:21 UTC (permalink / raw)
  To: 9fans

> I tried something like that, and what I tried did not work, but my failure
> might differ from your xfer9p (have thrown it away, cannot compare).
> Still I'm wondering, why use own code instead of simply using read9pmsg?

The reason not to use read9pmsg is that I don't want to
get caught with a buffer that's not big enough, so I realloc
it (when necessary) after reading the header length.
You can't use read9pmsg to do that unless you know
basically everything about what read9pmsg is doing, at
which point it's easier not to use it.

Or rather, it would be easier, if I could manage to write
the correct five lines.

Russ



^ permalink raw reply	[flat|nested] 10+ messages in thread
* Re: [9fans] fs error msg: didn't like (1460 274) byte message
@ 2002-09-25 18:24 Russ Cox
  2002-09-25 18:44 ` Axel Belinfante
  2002-09-25 21:12 ` Axel Belinfante
  0 siblings, 2 replies; 10+ messages in thread
From: Russ Cox @ 2002-09-25 18:24 UTC (permalink / raw)
  To: 9fans

The problem is the buffer can be arbitrarily sized, though
typically 8192+IOHDRSZ is the max a client and server will
agree on.  Cpu uses a much larger max size to improve graphics
performance.

Here's a fixed xfer9p.  I forgot that the initial count
includes itself.

void
xfer9p(int from, int to)
{
	char *buf;
	uint nbuf;
	int n;

	nbuf = 256;
	buf = malloc(nbuf);
	if(buf == nil)
		sysfatal("xfer: malloc %ud: %r", nbuf);

	for(;;){
		if(readn(from, buf, 4) != 4)
			break;
		n = GBIT32(buf);
		if(n > nbuf){
			nbuf = n+8192;	/* 8192: slop */
			buf = realloc(buf, nbuf);
			if(buf == nil)
				sysfatal("xfer: realloc %ud: %r", nbuf);
		}
		if(readn(from, buf+4, n-4) != n-4)
			break;
		if(write(to, buf, n) != n)
			break;
	}
}

Russ


^ permalink raw reply	[flat|nested] 10+ messages in thread
* [9fans] fs error msg: didn't like (1460 274) byte message
@ 2002-09-24 23:25 Axel Belinfante
  0 siblings, 0 replies; 10+ messages in thread
From: Axel Belinfante @ 2002-09-24 23:25 UTC (permalink / raw)
  To: 9fans

Just had a problem copying/saving a file from acme at home
(over a right now not excitingly fast connection)
to the fake worm server at work.
When it happened, acme hang (until I fysically disrupted the connection
-- could not think of something else) and cp also hang.
(after disrupting the connection, acme returned to a usable state,
so I could save the file to local disk -- many thanks to the person
bringing up this kind of things (hanging fs connection) some days ago!)
When it happened, I had a 'C fs' window open, in which appeared:

didn't like 1460 byte message
didn't like 274 byte message

Scenario:
working at home on a laptop that has had the 60Mb update;
the kernel is a few days older, of september 18.
Because I have this funny router at the home  end of the cable
modem connection, and it does not let il through, I have

cpu%  cat /rc/bin/service/tcp564
#!/bin/rc
exec aux/trampoline il!super!9fs
cpu%

on the cpu server and run '9fs cpu' to connect to the file server.
(the cpu server is diskless and gets root from fs; also its
kernel is from september 18, I think).

The problem seems reproducible: when saving the remote file
from acme failed, I saved it locally and tried then copying it to fs,
with the same result. However, doing a 'cat > target'
in the cpu window, and pasting the text from the (short) file there,
followed by ^D was succesful (remember, cpu server gets root from fs).

The fs kernel is a bit old, from May 28. Can that explain this?

Is there anything easy I could try to get more insight?
I tried 'flag chat' on the fs, but that did not seem
to give info on the 'not-liked' packages -- but maybe I overlooked.

I'll keep the latop running and connected, in case there are some
things I could try.

Just tried to open a new window, run 9fs cpu, and tried again to
copy the same file from local disk to remote fs. Same result.

Axel (concerned, but still hoping for a simple explanation...)


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2002-09-26  8:49 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-09-24 23:42 [9fans] fs error msg: didn't like (1460 274) byte message Russ Cox
2002-09-25 11:45 ` Axel Belinfante
2002-09-25 18:19 ` Axel Belinfante
  -- strict thread matches above, loose matches on Subject: below --
2002-09-25 21:30 Russ Cox
2002-09-26  8:49 ` Axel Belinfante
2002-09-25 21:21 Russ Cox
2002-09-25 18:24 Russ Cox
2002-09-25 18:44 ` Axel Belinfante
2002-09-25 21:12 ` Axel Belinfante
2002-09-24 23:25 Axel Belinfante

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).