mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
ip/pppoe: properly zero-pad ethernet frames, optimize framing, limit mtu
we should properly zero-pad the ethernet frames we send out instead of sending random garbage. for ppp -> ethernet, the ethernet header is fixed, so we can generate it once before the read()/write() loop. Use a 1514 byte buffer for all ethernet frames as the maximum, and limit the mtu to 1514-14-8 -> 1492.
This commit is contained in:
parent
aeb857e367
commit
e4373dd103
1 changed files with 84 additions and 84 deletions
|
@ -7,6 +7,70 @@
|
|||
#include <libc.h>
|
||||
#include <ip.h>
|
||||
|
||||
typedef struct Etherhdr Etherhdr;
|
||||
struct Etherhdr {
|
||||
uchar dst[6];
|
||||
uchar src[6];
|
||||
uchar type[2];
|
||||
};
|
||||
|
||||
enum {
|
||||
EtherHdrSz = 6+6+2,
|
||||
EtherMintu = 60,
|
||||
EtherMaxtu = 1500+EtherHdrSz,
|
||||
|
||||
EtherPppoeDiscovery = 0x8863,
|
||||
EtherPppoeSession = 0x8864,
|
||||
};
|
||||
|
||||
uchar etherbcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
typedef struct Pppoehdr Pppoehdr;
|
||||
struct Pppoehdr {
|
||||
uchar verstype;
|
||||
uchar code;
|
||||
uchar sessid[2];
|
||||
uchar length[2]; /* of payload */
|
||||
};
|
||||
|
||||
enum {
|
||||
PppoeHdrSz = 1+1+2+2,
|
||||
Hdr = EtherHdrSz+PppoeHdrSz,
|
||||
Maxmtu = EtherMaxtu - (Hdr+2), /* 2 bytes for PPP header */
|
||||
};
|
||||
|
||||
enum {
|
||||
VersType = 0x11,
|
||||
|
||||
/* Discovery codes */
|
||||
CodeDiscInit = 0x09, /* discovery init */
|
||||
CodeDiscOffer = 0x07, /* discovery offer */
|
||||
CodeDiscReq = 0x19, /* discovery request */
|
||||
CodeDiscSess = 0x65, /* session confirmation */
|
||||
CodeDiscTerm = 0xa7,
|
||||
|
||||
/* Session codes */
|
||||
CodeSession = 0x00,
|
||||
};
|
||||
|
||||
typedef struct Taghdr Taghdr;
|
||||
struct Taghdr {
|
||||
uchar type[2];
|
||||
uchar length[2]; /* of value */
|
||||
};
|
||||
|
||||
enum {
|
||||
TagEnd = 0x0000, /* end of tag list */
|
||||
TagSrvName = 0x0101, /* service name */
|
||||
TagAcName = 0x0102, /* access concentrator name */
|
||||
TagHostUniq = 0x0103, /* nonce */
|
||||
TagAcCookie = 0x0104, /* a.c. cookie */
|
||||
TagVendSpec = 0x0105, /* vendor specific */
|
||||
TagRelaySessId = 0x0110, /* relay session id */
|
||||
TagSrvNameErr = 0x0201, /* service name error (ascii) */
|
||||
TagAcSysErr = 0x0202, /* a.c. system error */
|
||||
};
|
||||
|
||||
void dumppkt(uchar*);
|
||||
uchar *findtag(uchar*, int, int*, int);
|
||||
void hexdump(uchar*, int);
|
||||
|
@ -32,7 +96,7 @@ uchar *cookie;
|
|||
int cookielen;
|
||||
uchar etherdst[6];
|
||||
uchar ethersrc[6];
|
||||
int mtu = 1492;
|
||||
int mtu = Maxmtu;
|
||||
int pktcompress, hdrcompress;
|
||||
char *baud;
|
||||
|
||||
|
@ -97,6 +161,8 @@ main(int argc, char **argv)
|
|||
break;
|
||||
case 'm':
|
||||
mtu = atoi(EARGF(usage()));
|
||||
if(mtu > Maxmtu)
|
||||
mtu = Maxmtu;
|
||||
break;
|
||||
case 'i':
|
||||
ipnet4 = EARGF(usage());
|
||||
|
@ -150,23 +216,6 @@ main(int argc, char **argv)
|
|||
execppp(pppoe(dev));
|
||||
}
|
||||
|
||||
typedef struct Etherhdr Etherhdr;
|
||||
struct Etherhdr {
|
||||
uchar dst[6];
|
||||
uchar src[6];
|
||||
uchar type[2];
|
||||
};
|
||||
|
||||
enum {
|
||||
EtherHdrSz = 6+6+2,
|
||||
EtherMintu = 60,
|
||||
|
||||
EtherPppoeDiscovery = 0x8863,
|
||||
EtherPppoeSession = 0x8864,
|
||||
};
|
||||
|
||||
uchar etherbcast[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
int
|
||||
etherhdr(uchar *pkt, uchar *dst, int type)
|
||||
{
|
||||
|
@ -178,33 +227,6 @@ etherhdr(uchar *pkt, uchar *dst, int type)
|
|||
return EtherHdrSz;
|
||||
}
|
||||
|
||||
typedef struct Pppoehdr Pppoehdr;
|
||||
struct Pppoehdr {
|
||||
uchar verstype;
|
||||
uchar code;
|
||||
uchar sessid[2];
|
||||
uchar length[2]; /* of payload */
|
||||
};
|
||||
|
||||
enum {
|
||||
PppoeHdrSz = 1+1+2+2,
|
||||
Hdr = EtherHdrSz+PppoeHdrSz,
|
||||
};
|
||||
|
||||
enum {
|
||||
VersType = 0x11,
|
||||
|
||||
/* Discovery codes */
|
||||
CodeDiscInit = 0x09, /* discovery init */
|
||||
CodeDiscOffer = 0x07, /* discovery offer */
|
||||
CodeDiscReq = 0x19, /* discovery request */
|
||||
CodeDiscSess = 0x65, /* session confirmation */
|
||||
CodeDiscTerm = 0xa7,
|
||||
|
||||
/* Session codes */
|
||||
CodeSession = 0x00,
|
||||
};
|
||||
|
||||
int
|
||||
pppoehdr(uchar *pkt, int code, int sessid)
|
||||
{
|
||||
|
@ -217,24 +239,6 @@ pppoehdr(uchar *pkt, int code, int sessid)
|
|||
return PppoeHdrSz;
|
||||
}
|
||||
|
||||
typedef struct Taghdr Taghdr;
|
||||
struct Taghdr {
|
||||
uchar type[2];
|
||||
uchar length[2]; /* of value */
|
||||
};
|
||||
|
||||
enum {
|
||||
TagEnd = 0x0000, /* end of tag list */
|
||||
TagSrvName = 0x0101, /* service name */
|
||||
TagAcName = 0x0102, /* access concentrator name */
|
||||
TagHostUniq = 0x0103, /* nonce */
|
||||
TagAcCookie = 0x0104, /* a.c. cookie */
|
||||
TagVendSpec = 0x0105, /* vendor specific */
|
||||
TagRelaySessId = 0x0110, /* relay session id */
|
||||
TagSrvNameErr = 0x0201, /* service name error (ascii) */
|
||||
TagAcSysErr = 0x0202, /* a.c. system error */
|
||||
};
|
||||
|
||||
int
|
||||
tag(uchar *pkt, int type, void *value, int nvalue)
|
||||
{
|
||||
|
@ -473,11 +477,9 @@ int
|
|||
pppoe(char *ether)
|
||||
{
|
||||
char buf[128];
|
||||
uchar pkt[1520];
|
||||
uchar pkt[EtherMaxtu];
|
||||
int dfd, sfd, p[2], n, sz, timeout;
|
||||
Pppoehdr *ph;
|
||||
|
||||
ph = (Pppoehdr*)(pkt+EtherHdrSz);
|
||||
snprint(buf, sizeof buf, "%s!%d", ether, EtherPppoeDiscovery);
|
||||
if((dfd = dial(buf, nil, nil, nil)) < 0)
|
||||
fatal("dial %s: %r\n", buf);
|
||||
|
@ -549,16 +551,17 @@ Restart:
|
|||
break;
|
||||
case 0:
|
||||
close(dfd);
|
||||
while((n = read(sfd, pkt, sizeof pkt)) > 0){
|
||||
if(malformed(pkt, n, EtherPppoeSession)
|
||||
|| ph->code != 0x00 || nhgets(ph->sessid) != sessid){
|
||||
if(debug)
|
||||
fprint(2, "malformed session pkt: %r\n");
|
||||
if(debug)
|
||||
dumppkt(pkt);
|
||||
|
||||
pppoehdr((uchar*)buf, 0x00, sessid);
|
||||
|
||||
while((sz = read(sfd, pkt, sizeof pkt)) > 0){
|
||||
if(sz < Hdr
|
||||
|| pkt[EtherHdrSz+1] != 0x00 /* code */
|
||||
|| pkt[EtherHdrSz+2] != (uchar)buf[2] /* sessid[0] */
|
||||
|| pkt[EtherHdrSz+3] != (uchar)buf[3] /* sessid[1] */
|
||||
|| (n = nhgets(pkt+Hdr-2)) > sz-Hdr)
|
||||
continue;
|
||||
}
|
||||
if(write(p[0], pkt+Hdr, nhgets(ph->length)) < 0){
|
||||
if(write(p[0], pkt+Hdr, n) < 0){
|
||||
if(debug)
|
||||
fprint(2, "write to ppp failed: %r\n");
|
||||
break;
|
||||
|
@ -574,17 +577,14 @@ Restart:
|
|||
break;
|
||||
case 0:
|
||||
close(dfd);
|
||||
|
||||
etherhdr(pkt, etherdst, EtherPppoeSession);
|
||||
pppoehdr(pkt+EtherHdrSz, 0x00, sessid);
|
||||
|
||||
while((n = read(p[0], pkt+Hdr, sizeof pkt-Hdr)) > 0){
|
||||
etherhdr(pkt, etherdst, EtherPppoeSession);
|
||||
pppoehdr(pkt+EtherHdrSz, 0x00, sessid);
|
||||
hnputs(pkt+Hdr-2, n);
|
||||
sz = Hdr+n;
|
||||
if(debug > 1){
|
||||
dumppkt(pkt);
|
||||
hexdump(pkt, sz);
|
||||
}
|
||||
if(sz < EtherMintu)
|
||||
sz = EtherMintu;
|
||||
for(sz = Hdr+n; sz < EtherMintu; sz++)
|
||||
pkt[sz] = 0;
|
||||
if(write(sfd, pkt, sz) < 0){
|
||||
if(debug)
|
||||
fprint(2, "write to ether failed: %r");
|
||||
|
|
Loading…
Reference in a new issue