devip: add support for IPv6
Addresses are now stored as uchar[16] instead of ulong, with enough room for IPv6. Generic IP functions have been removed from devip.c and replaced by libip, imported from Plan 9. Names and addresses are resolved using either gethostbyname() or getaddrinfo() functions. On Windows, IPv6 name resolution is not enabled, because mingw32 doesn't provide inet_ntop(). R=rsc http://codereview.appspot.com/6408044
This commit is contained in:
@ -3,12 +3,14 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
#include "ip.h"
|
||||
|
||||
#include "devip.h"
|
||||
|
||||
@ -16,6 +18,14 @@
|
||||
#undef accept
|
||||
#undef bind
|
||||
|
||||
static int
|
||||
family(unsigned char *addr)
|
||||
{
|
||||
if(isv4(addr))
|
||||
return AF_INET;
|
||||
return AF_INET6;
|
||||
}
|
||||
|
||||
void
|
||||
osipinit(void)
|
||||
{
|
||||
@ -26,7 +36,7 @@ osipinit(void)
|
||||
}
|
||||
|
||||
int
|
||||
so_socket(int type)
|
||||
so_socket(int type, unsigned char *addr)
|
||||
{
|
||||
int fd, one;
|
||||
|
||||
@ -41,7 +51,7 @@ so_socket(int type)
|
||||
break;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, type, 0);
|
||||
fd = socket(family(addr), type, 0);
|
||||
if(fd < 0)
|
||||
oserror();
|
||||
|
||||
@ -54,36 +64,52 @@ so_socket(int type)
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
so_connect(int fd, unsigned long raddr, unsigned short rport)
|
||||
so_connect(int fd, unsigned char *raddr, unsigned short rport)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
hnputs(&sin.sin_port, rport);
|
||||
hnputl(&sin.sin_addr.s_addr, raddr);
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
|
||||
if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
||||
ss.ss_family = family(raddr);
|
||||
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport);
|
||||
v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport);
|
||||
memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr));
|
||||
break;
|
||||
}
|
||||
|
||||
if(connect(fd, (struct sockaddr*)&ss, sizeof(ss)) < 0)
|
||||
oserror();
|
||||
}
|
||||
|
||||
void
|
||||
so_getsockname(int fd, unsigned long *laddr, unsigned short *lport)
|
||||
so_getsockname(int fd, unsigned char *laddr, unsigned short *lport)
|
||||
{
|
||||
socklen_t len;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
len = sizeof(sin);
|
||||
if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0)
|
||||
len = sizeof(ss);
|
||||
if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0)
|
||||
oserror();
|
||||
|
||||
if(sin.sin_family != AF_INET || len != sizeof(sin))
|
||||
error("not AF_INET");
|
||||
|
||||
*laddr = nhgetl(&sin.sin_addr.s_addr);
|
||||
*lport = nhgets(&sin.sin_port);
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
|
||||
*lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
|
||||
*lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
|
||||
break;
|
||||
default:
|
||||
error("not AF_INET or AF_INET6");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -94,30 +120,37 @@ so_listen(int fd)
|
||||
}
|
||||
|
||||
int
|
||||
so_accept(int fd, unsigned long *raddr, unsigned short *rport)
|
||||
so_accept(int fd, unsigned char *raddr, unsigned short *rport)
|
||||
{
|
||||
int nfd;
|
||||
socklen_t len;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
len = sizeof(sin);
|
||||
nfd = accept(fd, (struct sockaddr*)&sin, &len);
|
||||
len = sizeof(ss);
|
||||
nfd = accept(fd, (struct sockaddr*)&ss, &len);
|
||||
if(nfd < 0)
|
||||
oserror();
|
||||
|
||||
if(sin.sin_family != AF_INET || len != sizeof(sin))
|
||||
error("not AF_INET");
|
||||
|
||||
*raddr = nhgetl(&sin.sin_addr.s_addr);
|
||||
*rport = nhgets(&sin.sin_port);
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
|
||||
*rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
|
||||
*rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
|
||||
break;
|
||||
default:
|
||||
error("not AF_INET or AF_INET6");
|
||||
}
|
||||
return nfd;
|
||||
}
|
||||
|
||||
void
|
||||
so_bind(int fd, int su, unsigned short port)
|
||||
so_bind(int fd, int su, unsigned short port, unsigned char *addr)
|
||||
{
|
||||
int i, one;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
one = 1;
|
||||
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){
|
||||
@ -127,21 +160,37 @@ so_bind(int fd, int su, unsigned short port)
|
||||
|
||||
if(su) {
|
||||
for(i = 600; i < 1024; i++) {
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = i;
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
ss.ss_family = family(addr);
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
((struct sockaddr_in*)&ss)->sin_port = i;
|
||||
break;
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6*)&ss)->sin6_port = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&ss, sizeof(ss)) >= 0)
|
||||
return;
|
||||
}
|
||||
oserror();
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
hnputs(&sin.sin_port, port);
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
ss.ss_family = family(addr);
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
hnputs(&((struct sockaddr_in*)&ss)->sin_port, port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port);
|
||||
break;
|
||||
}
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&ss, sizeof(ss)) < 0)
|
||||
oserror();
|
||||
}
|
||||
|
||||
@ -170,16 +219,28 @@ so_gethostbyname(char *host, char**hostv, int n)
|
||||
char*
|
||||
hostlookup(char *host)
|
||||
{
|
||||
char buf[100];
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
uchar *p;
|
||||
struct hostent *he;
|
||||
struct addrinfo *result;
|
||||
|
||||
he = gethostbyname(host);
|
||||
if(he != 0 && he->h_addr_list[0]) {
|
||||
p = (uchar*)he->h_addr_list[0];
|
||||
sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
|
||||
} else if(getaddrinfo(host, NULL, NULL, &result) == 0) {
|
||||
switch (result->ai_family) {
|
||||
case AF_INET:
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in*)result->ai_addr)->sin_addr, buf, sizeof(buf));
|
||||
break;
|
||||
case AF_INET6:
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, buf, sizeof(buf));
|
||||
break;
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
} else
|
||||
strcpy(buf, host);
|
||||
return nil;
|
||||
|
||||
return strdup(buf);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
#include <windows.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
#include "ip.h"
|
||||
|
||||
#include "devip.h"
|
||||
|
||||
@ -15,6 +17,14 @@
|
||||
#undef accept
|
||||
#undef bind
|
||||
|
||||
static int
|
||||
family(unsigned char *addr)
|
||||
{
|
||||
if(isv4(addr))
|
||||
return AF_INET;
|
||||
return AF_INET6;
|
||||
}
|
||||
|
||||
void
|
||||
osipinit(void)
|
||||
{
|
||||
@ -29,7 +39,7 @@ osipinit(void)
|
||||
}
|
||||
|
||||
int
|
||||
so_socket(int type)
|
||||
so_socket(int type, unsigned char *addr)
|
||||
{
|
||||
int fd, one;
|
||||
|
||||
@ -44,7 +54,7 @@ so_socket(int type)
|
||||
break;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, type, 0);
|
||||
fd = socket(family(addr), type, 0);
|
||||
if(fd < 0)
|
||||
oserror();
|
||||
|
||||
@ -59,34 +69,51 @@ so_socket(int type)
|
||||
|
||||
|
||||
void
|
||||
so_connect(int fd, unsigned long raddr, unsigned short rport)
|
||||
so_connect(int fd, unsigned char *raddr, unsigned short rport)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
hnputs(&sin.sin_port, rport);
|
||||
hnputl(&sin.sin_addr.s_addr, raddr);
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
|
||||
if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
||||
ss.ss_family = family(raddr);
|
||||
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport);
|
||||
v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr);
|
||||
break;
|
||||
case AF_INET6:
|
||||
hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport);
|
||||
memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr));
|
||||
break;
|
||||
}
|
||||
|
||||
if(connect(fd, (struct sockaddr*)&ss, sizeof(ss)) < 0)
|
||||
oserror();
|
||||
}
|
||||
|
||||
void
|
||||
so_getsockname(int fd, unsigned long *laddr, unsigned short *lport)
|
||||
so_getsockname(int fd, unsigned char *laddr, unsigned short *lport)
|
||||
{
|
||||
int len;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
len = sizeof(sin);
|
||||
if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0)
|
||||
len = sizeof(ss);
|
||||
if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0)
|
||||
oserror();
|
||||
|
||||
if(sin.sin_family != AF_INET || len != sizeof(sin))
|
||||
error("not AF_INET");
|
||||
|
||||
*laddr = nhgetl(&sin.sin_addr.s_addr);
|
||||
*lport = nhgets(&sin.sin_port);
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
|
||||
*lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
|
||||
*lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
|
||||
break;
|
||||
default:
|
||||
error("not AF_INET or AF_INET6");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -97,53 +124,77 @@ so_listen(int fd)
|
||||
}
|
||||
|
||||
int
|
||||
so_accept(int fd, unsigned long *raddr, unsigned short *rport)
|
||||
so_accept(int fd, unsigned char *raddr, unsigned short *rport)
|
||||
{
|
||||
int nfd, len;
|
||||
struct sockaddr_in sin;
|
||||
int nfd;
|
||||
int len;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
len = sizeof(sin);
|
||||
nfd = accept(fd, (struct sockaddr*)&sin, &len);
|
||||
len = sizeof(ss);
|
||||
nfd = accept(fd, (struct sockaddr*)&ss, &len);
|
||||
if(nfd < 0)
|
||||
oserror();
|
||||
|
||||
if(sin.sin_family != AF_INET || len != sizeof(sin))
|
||||
error("not AF_INET");
|
||||
|
||||
*raddr = nhgetl(&sin.sin_addr.s_addr);
|
||||
*rport = nhgets(&sin.sin_port);
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
|
||||
*rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
|
||||
*rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
|
||||
break;
|
||||
default:
|
||||
error("not AF_INET or AF_INET6");
|
||||
}
|
||||
return nfd;
|
||||
}
|
||||
|
||||
void
|
||||
so_bind(int fd, int su, unsigned short port)
|
||||
so_bind(int fd, int su, unsigned short port, unsigned char *addr)
|
||||
{
|
||||
int i, one;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
one = 1;
|
||||
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){
|
||||
oserrstr();
|
||||
print("setsockopt: %s", up->errstr);
|
||||
print("setsockopt: %r");
|
||||
}
|
||||
|
||||
if(su) {
|
||||
for(i = 600; i < 1024; i++) {
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = i;
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
ss.ss_family = family(addr);
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
((struct sockaddr_in*)&ss)->sin_port = i;
|
||||
break;
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6*)&ss)->sin6_port = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&ss, sizeof(ss)) >= 0)
|
||||
return;
|
||||
}
|
||||
oserror();
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
hnputs(&sin.sin_port, port);
|
||||
memset(&ss, 0, sizeof(ss));
|
||||
ss.ss_family = family(addr);
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
||||
switch(ss.ss_family){
|
||||
case AF_INET:
|
||||
hnputs(&((struct sockaddr_in*)&ss)->sin_port, port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port);
|
||||
break;
|
||||
}
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&ss, sizeof(ss)) < 0)
|
||||
oserror();
|
||||
}
|
||||
|
||||
@ -174,7 +225,7 @@ hostlookup(char *host)
|
||||
{
|
||||
char buf[100];
|
||||
uchar *p;
|
||||
HOSTENT *he;
|
||||
struct hostent *he;
|
||||
|
||||
he = gethostbyname(host);
|
||||
if(he != 0 && he->h_addr_list[0]) {
|
||||
|
219
kern/devip.c
219
kern/devip.c
@ -3,14 +3,10 @@
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
#include "ip.h"
|
||||
|
||||
#include "devip.h"
|
||||
|
||||
void hnputl(void *p, unsigned long v);
|
||||
void hnputs(void *p, unsigned short v);
|
||||
unsigned long nhgetl(void *p);
|
||||
unsigned short nhgets(void *p);
|
||||
unsigned long parseip(char *to, char *from);
|
||||
void csclose(Chan*);
|
||||
long csread(Chan*, void*, long, vlong);
|
||||
long cswrite(Chan*, void*, long, vlong);
|
||||
@ -37,6 +33,7 @@ enum
|
||||
#define CONV(x) ((int)(((x).path >> 4)&0xfff))
|
||||
#define PROTO(x) ((int)(((x).path >> 16)&0xff))
|
||||
#define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y))
|
||||
#define ipzero(x) memset(x, 0, IPaddrlen)
|
||||
|
||||
typedef struct Proto Proto;
|
||||
typedef struct Conv Conv;
|
||||
@ -48,9 +45,9 @@ struct Conv
|
||||
int perm;
|
||||
char owner[KNAMELEN];
|
||||
char* state;
|
||||
ulong laddr;
|
||||
uchar laddr[IPaddrlen];
|
||||
ushort lport;
|
||||
ulong raddr;
|
||||
uchar raddr[IPaddrlen];
|
||||
ushort rport;
|
||||
int restricted;
|
||||
char cerr[KNAMELEN];
|
||||
@ -71,7 +68,6 @@ struct Proto
|
||||
|
||||
static int np;
|
||||
static Proto proto[MAXPROTO];
|
||||
int eipfmt(Fmt*);
|
||||
|
||||
static Conv* protoclone(Proto*, char*, int);
|
||||
static void setladdr(Conv*);
|
||||
@ -222,7 +218,7 @@ Chan *
|
||||
ipopen(Chan *c, int omode)
|
||||
{
|
||||
Proto *p;
|
||||
ulong raddr;
|
||||
uchar raddr[IPaddrlen];
|
||||
ushort rport;
|
||||
int perm, sfd;
|
||||
Conv *cv, *lcv;
|
||||
@ -286,13 +282,13 @@ ipopen(Chan *c, int omode)
|
||||
case Qlisten:
|
||||
p = &proto[PROTO(c->qid)];
|
||||
lcv = p->conv[CONV(c->qid)];
|
||||
sfd = so_accept(lcv->sfd, &raddr, &rport);
|
||||
sfd = so_accept(lcv->sfd, raddr, &rport);
|
||||
cv = protoclone(p, up->user, sfd);
|
||||
if(cv == 0) {
|
||||
close(sfd);
|
||||
error(Enodev);
|
||||
}
|
||||
cv->raddr = raddr;
|
||||
ipmove(cv->raddr, raddr);
|
||||
cv->rport = rport;
|
||||
setladdr(cv);
|
||||
cv->state = "Established";
|
||||
@ -324,8 +320,8 @@ ipclose(Chan *c)
|
||||
strcpy(cc->owner, "network");
|
||||
cc->perm = 0666;
|
||||
cc->state = "Closed";
|
||||
cc->laddr = 0;
|
||||
cc->raddr = 0;
|
||||
ipzero(cc->laddr);
|
||||
ipzero(cc->raddr);
|
||||
cc->lport = 0;
|
||||
cc->rport = 0;
|
||||
close(cc->sfd);
|
||||
@ -339,7 +335,7 @@ ipread(Chan *ch, void *a, long n, vlong offset)
|
||||
int r;
|
||||
Conv *c;
|
||||
Proto *x;
|
||||
uchar ip[4];
|
||||
uchar ip[IPaddrlen];
|
||||
char buf[128], *p;
|
||||
|
||||
/*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/
|
||||
@ -358,12 +354,12 @@ ipread(Chan *ch, void *a, long n, vlong offset)
|
||||
return readstr(offset, p, n, buf);
|
||||
case Qremote:
|
||||
c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
|
||||
hnputl(ip, c->raddr);
|
||||
ipmove(ip, c->raddr);
|
||||
sprint(buf, "%I!%d\n", ip, c->rport);
|
||||
return readstr(offset, p, n, buf);
|
||||
case Qlocal:
|
||||
c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
|
||||
hnputl(ip, c->laddr);
|
||||
ipmove(ip, c->laddr);
|
||||
sprint(buf, "%I!%d\n", ip, c->lport);
|
||||
return readstr(offset, p, n, buf);
|
||||
case Qstatus:
|
||||
@ -386,7 +382,7 @@ ipread(Chan *ch, void *a, long n, vlong offset)
|
||||
static void
|
||||
setladdr(Conv *c)
|
||||
{
|
||||
so_getsockname(c->sfd, &c->laddr, &c->lport);
|
||||
so_getsockname(c->sfd, c->laddr, &c->lport);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -395,23 +391,27 @@ setlport(Conv *c)
|
||||
if(c->restricted == 0 && c->lport == 0)
|
||||
return;
|
||||
|
||||
so_bind(c->sfd, c->restricted, c->lport);
|
||||
if(c->sfd == -1)
|
||||
c->sfd = so_socket(c->p->stype, c->laddr);
|
||||
|
||||
so_bind(c->sfd, c->restricted, c->lport, c->laddr);
|
||||
}
|
||||
|
||||
static void
|
||||
setladdrport(Conv *c, char *str)
|
||||
{
|
||||
char *p, addr[4];
|
||||
char *p;
|
||||
uchar addr[IPaddrlen];
|
||||
|
||||
p = strchr(str, '!');
|
||||
if(p == 0) {
|
||||
p = str;
|
||||
c->laddr = 0;
|
||||
ipzero(c->laddr);
|
||||
}
|
||||
else {
|
||||
*p++ = 0;
|
||||
parseip(addr, str);
|
||||
c->laddr = nhgetl((uchar*)addr);
|
||||
ipmove(c->laddr, addr);
|
||||
}
|
||||
if(*p == '*')
|
||||
c->lport = 0;
|
||||
@ -424,14 +424,15 @@ setladdrport(Conv *c, char *str)
|
||||
static char*
|
||||
setraddrport(Conv *c, char *str)
|
||||
{
|
||||
char *p, addr[4];
|
||||
char *p;
|
||||
uchar addr[IPaddrlen];
|
||||
|
||||
p = strchr(str, '!');
|
||||
if(p == 0)
|
||||
return "malformed address";
|
||||
*p++ = 0;
|
||||
parseip(addr, str);
|
||||
c->raddr = nhgetl((uchar*)addr);
|
||||
ipmove(c->raddr, addr);
|
||||
c->rport = atoi(p);
|
||||
p = strchr(p, '!');
|
||||
if(p) {
|
||||
@ -480,6 +481,8 @@ ipwrite(Chan *ch, void *a, long n, vlong offset)
|
||||
setlport(c);
|
||||
break;
|
||||
}
|
||||
if(c->sfd == -1)
|
||||
c->sfd = so_socket(c->p->stype, c->raddr);
|
||||
so_connect(c->sfd, c->raddr, c->rport);
|
||||
setladdr(c);
|
||||
c->state = "Established";
|
||||
@ -565,13 +568,11 @@ protoclone(Proto *p, char *user, int nfd)
|
||||
c->perm = 0660;
|
||||
c->state = "Closed";
|
||||
c->restricted = 0;
|
||||
c->laddr = 0;
|
||||
c->raddr = 0;
|
||||
ipzero(c->laddr);
|
||||
ipzero(c->raddr);
|
||||
c->lport = 0;
|
||||
c->rport = 0;
|
||||
c->sfd = nfd;
|
||||
if(nfd == -1)
|
||||
c->sfd = so_socket(p->stype);
|
||||
|
||||
unlock(&c->r.lk);
|
||||
unlock(&p->l);
|
||||
@ -579,145 +580,6 @@ protoclone(Proto *p, char *user, int nfd)
|
||||
return c;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
Isprefix= 16,
|
||||
};
|
||||
|
||||
uchar prefixvals[256] =
|
||||
{
|
||||
/*0x00*/ 0 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x80*/ 1 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xC0*/ 2 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xD0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xE0*/ 3 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xF0*/ 4 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xF8*/ 5 | Isprefix,
|
||||
0, 0, 0,
|
||||
/*0xFC*/ 6 | Isprefix,
|
||||
0,
|
||||
/*0xFE*/ 7 | Isprefix,
|
||||
/*0xFF*/ 8 | Isprefix,
|
||||
};
|
||||
|
||||
int
|
||||
eipfmt(Fmt *f)
|
||||
{
|
||||
char buf[5*8];
|
||||
static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
|
||||
static char *ifmt = "%d.%d.%d.%d";
|
||||
uchar *p, ip[16];
|
||||
ulong ul;
|
||||
|
||||
switch(f->r) {
|
||||
case 'E': /* Ethernet address */
|
||||
p = va_arg(f->args, uchar*);
|
||||
snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
return fmtstrcpy(f, buf);
|
||||
|
||||
case 'I':
|
||||
ul = va_arg(f->args, ulong);
|
||||
hnputl(ip, ul);
|
||||
snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]);
|
||||
return fmtstrcpy(f, buf);
|
||||
}
|
||||
return fmtstrcpy(f, "(eipfmt)");
|
||||
}
|
||||
|
||||
void
|
||||
hnputl(void *p, unsigned long v)
|
||||
{
|
||||
unsigned char *a;
|
||||
|
||||
a = p;
|
||||
a[0] = v>>24;
|
||||
a[1] = v>>16;
|
||||
a[2] = v>>8;
|
||||
a[3] = v;
|
||||
}
|
||||
|
||||
void
|
||||
hnputs(void *p, unsigned short v)
|
||||
{
|
||||
unsigned char *a;
|
||||
|
||||
a = p;
|
||||
a[0] = v>>8;
|
||||
a[1] = v;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
nhgetl(void *p)
|
||||
{
|
||||
unsigned char *a;
|
||||
a = p;
|
||||
return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);
|
||||
}
|
||||
|
||||
unsigned short
|
||||
nhgets(void *p)
|
||||
{
|
||||
unsigned char *a;
|
||||
a = p;
|
||||
return (a[0]<<8)|(a[1]<<0);
|
||||
}
|
||||
|
||||
#define CLASS(p) ((*(unsigned char*)(p))>>6)
|
||||
|
||||
unsigned long
|
||||
parseip(char *to, char *from)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
p = from;
|
||||
memset(to, 0, 4);
|
||||
for(i = 0; i < 4 && *p; i++){
|
||||
to[i] = strtoul(p, &p, 10);
|
||||
if(*p != '.' && *p != 0){
|
||||
memset(to, 0, 4);
|
||||
return 0;
|
||||
}
|
||||
if(*p == '.')
|
||||
p++;
|
||||
}
|
||||
switch(CLASS(to)){
|
||||
case 0: /* class A - 1 byte net */
|
||||
case 1:
|
||||
if(i == 3){
|
||||
to[3] = to[2];
|
||||
to[2] = to[1];
|
||||
to[1] = 0;
|
||||
} else if (i == 2){
|
||||
to[3] = to[1];
|
||||
to[1] = 0;
|
||||
}
|
||||
break;
|
||||
case 2: /* class B - 2 byte net */
|
||||
if(i == 3){
|
||||
to[3] = to[2];
|
||||
to[2] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return nhgetl(to);
|
||||
}
|
||||
|
||||
void
|
||||
csclose(Chan *c)
|
||||
{
|
||||
@ -856,23 +718,17 @@ lookupport(char *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong
|
||||
lookuphost(char *s)
|
||||
static int
|
||||
lookuphost(char *s, uchar *to)
|
||||
{
|
||||
char to[4];
|
||||
ulong ip;
|
||||
|
||||
memset(to, 0, sizeof to);
|
||||
parseip(to, s);
|
||||
ip = nhgetl(to);
|
||||
if(ip != 0)
|
||||
return ip;
|
||||
if((s = hostlookup(s)) == nil)
|
||||
ipzero(to);
|
||||
if(parseip(to, s) != -1)
|
||||
return 0;
|
||||
if((s = hostlookup(s)) == nil)
|
||||
return -1;
|
||||
parseip(to, s);
|
||||
ip = nhgetl(to);
|
||||
free(s);
|
||||
return ip;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
@ -880,7 +736,7 @@ cswrite(Chan *c, void *a, long n, vlong offset)
|
||||
{
|
||||
char *f[4];
|
||||
char *s, *ns;
|
||||
ulong ip;
|
||||
uchar ip[IPaddrlen];
|
||||
int nf, port;
|
||||
|
||||
s = malloc(n+1);
|
||||
@ -900,8 +756,7 @@ cswrite(Chan *c, void *a, long n, vlong offset)
|
||||
if(port <= 0)
|
||||
error("no translation for port found");
|
||||
|
||||
ip = lookuphost(f[1]);
|
||||
if(ip == 0)
|
||||
if(lookuphost(f[1], ip) < 0)
|
||||
error("no translation for host found");
|
||||
|
||||
ns = smprint("/net/%s/clone %I!%d", f[0], ip, port);
|
||||
|
10
kern/devip.h
10
kern/devip.h
@ -4,14 +4,14 @@ enum
|
||||
S_UDP
|
||||
};
|
||||
|
||||
int so_socket(int type);
|
||||
void so_connect(int, unsigned long, unsigned short);
|
||||
void so_getsockname(int, unsigned long*, unsigned short*);
|
||||
void so_bind(int, int, unsigned short);
|
||||
int so_socket(int, unsigned char*);
|
||||
void so_connect(int, unsigned char*, unsigned short);
|
||||
void so_getsockname(int, unsigned char*, unsigned short*);
|
||||
void so_bind(int, int, unsigned short, unsigned char*);
|
||||
void so_listen(int);
|
||||
int so_send(int, void*, int, int);
|
||||
int so_recv(int, void*, int, int);
|
||||
int so_accept(int, unsigned long*, unsigned short*);
|
||||
int so_accept(int, unsigned char*, unsigned short*);
|
||||
int so_getservbyname(char*, char*, char*);
|
||||
int so_gethostbyname(char*, char**, int);
|
||||
|
||||
|
@ -375,12 +375,6 @@ Segment* data2txt(Segment*);
|
||||
Segment* dupseg(Segment**, int, int);
|
||||
Segment* newseg(int, ulong, ulong);
|
||||
Segment* seg(Proc*, ulong, int);
|
||||
void hnputv(void*, vlong);
|
||||
void hnputl(void*, ulong);
|
||||
void hnputs(void*, ushort);
|
||||
vlong nhgetv(void*);
|
||||
ulong nhgetl(void*);
|
||||
ushort nhgets(void*);
|
||||
ulong ticks(void);
|
||||
void osproc(Proc*);
|
||||
void osnewproc(Proc*);
|
||||
|
Reference in New Issue
Block a user