#include #include #include #define NODEFINE #include <9pm/u.h> #include <9pm/libc.h> #include <9pm/ns.h> #undef NODEFINE #include <9pm/devip.h> static long netread(Conv *c, void *data, long ndata) { long n; if((n=read(c->sfd, data, ndata)) < 0) pm_oserror(); return n; } static long netwrite(Conv *c, void *data, long ndata) { long n; if((n=write(c->sfd, data, ndata)) < 0){ pm_oserror(); pm_nexterror(); } return n; } static void netopen(Conv *c, int fd) { int n; char buf[64], num[12]; c->cfd = fd; c->sfd = -1; if((n=read(fd, num, sizeof(num)-1)) <= 0){ pm_oserror(); c->cfd = -1; close(fd); pm_nexterror(); } num[n] = '\0'; c->dirno = atoi(num); sprint(buf, "/net/%s/%d/data", c->p->name, c->dirno); if((fd = open(buf, ORDWR)) < 0){ pm_oserror(); close(c->cfd); c->cfd = -1; pm_nexterror(); } c->sfd = fd; } static void netclone(Conv *c) { int fd; char buf[64]; sprint(buf, "/net/%s/clone", c->p->name); if((fd = open(buf, ORDWR)) < 0){ pm_oserror(); pm_nexterror(); } netopen(c, fd); } static void netconnect(Conv *c) { uchar ip[4]; hnputl(ip, c->raddr); if(c->lport) { if(fprint(c->cfd, "connect %L %d", ip, c->rport, c->lport) < 0) { pm_oserror(); pm_nexterror(); } } else { if(fprint(c->cfd, "connect %L", ip, c->rport) < 0) { pm_oserror(); pm_nexterror(); } } } static void netannounce(Conv *c) { uchar ip[4]; hnputl(ip, c->raddr); if(fprint(c->cfd, "announce %L", ip, c->rport) < 0) { pm_oserror(); pm_nexterror(); } } static void netlisten(Conv *c, Conv *oc) { char buf[64]; int lfd; sprint(buf, "/net/%s/%d/listen", oc->p->name, oc->dirno); if((lfd = open(buf, OREAD)) < 0) { pm_oserror(); pm_nexterror(); } netopen(c, lfd); } static void netclose(Conv *c) { close(c->sfd); c->sfd = -1; close(c->cfd); c->cfd = -1; } /* takes two arguments (!) */ static int Lconv(va_list *va, Fconv *fp) { uchar* addr; ushort port; char buf[40]; addr = va_arg(*va, uchar*); port = va_arg(*va, int); /* not ushort */ if(addr == 0 && port == 0) snprint(buf, sizeof buf, "*"); else if(addr == 0) snprint(buf, sizeof buf, "%d", port); else if(port == 0) snprint(buf, sizeof buf, "%V!*", addr); else snprint(buf, sizeof buf, "%V!%d", addr, port); strconv(buf, fp); return 0; } static Proto ilproto = { "il", netread, netwrite, netclone, netconnect, netannounce, netlisten, netclose, 40, }; static Proto udpproto = { "udp", netread, netwrite, netclone, netconnect, netannounce, netlisten, netclose, 30, }; static Proto tcpproto = { "tcp", netread, netwrite, netclone, netconnect, netannounce, netlisten, netclose, 40, }; void ipinit(void (*inst)(Proto*)) { fmtinstall('V', eipconv); fmtinstall('L', Lconv); (*inst)(&tcpproto); (*inst)(&udpproto); (*inst)(&ilproto); }