devip: add "reflect" ctl message, fix memory leaks in icmpv6, fix source address for icmpttlexceeded, cleanup
parent
691370a08d
commit
638b4a1ec1
13
sys/man/3/ip
13
sys/man/3/ip
|
@ -194,16 +194,19 @@ Set the maximum transfer unit for this device to
|
|||
The mtu is the maximum size of the packet including any
|
||||
medium-specific headers.
|
||||
.TP
|
||||
.BI reassemble
|
||||
Reassemble IP fragments before forwarding to this interface
|
||||
.TP
|
||||
.BI iprouting\ n
|
||||
Allow
|
||||
.RI ( n
|
||||
is missing or non-zero) or disallow
|
||||
.RI ( n
|
||||
is 0) forwarding packets between this interface and
|
||||
others.
|
||||
is 0) forwarding packets between this interface and others.
|
||||
.TP
|
||||
.BI reflect\ n
|
||||
When forwarding, allow packets from this interface to be
|
||||
echoed back on the same interface.
|
||||
.TP
|
||||
.BI reassemble\ n
|
||||
Reassemble IP fragments before forwarding to this interface
|
||||
.
|
||||
.\" remainder from netif.c (thus called from devether.c),
|
||||
.\" except add6 and ra6 from ipifc.c
|
||||
|
|
|
@ -629,7 +629,8 @@ dodrops:
|
|||
|
||||
for(; xp != nil; xp = next){
|
||||
next = xp->list;
|
||||
icmphostunr(f, ifc, xp, Icmp6_adr_unreach, 1);
|
||||
icmphostunr6(f, ifc, xp, Icmp6_adr_unreach, 1);
|
||||
freeblist(xp);
|
||||
}
|
||||
|
||||
return nrxt;
|
||||
|
|
|
@ -215,22 +215,25 @@ ip4me(Fs *f, uchar ip4[4])
|
|||
}
|
||||
|
||||
void
|
||||
icmpttlexceeded(Fs *f, uchar *ia, Block *bp)
|
||||
icmpttlexceeded(Fs *f, Ipifc *ifc, Block *bp)
|
||||
{
|
||||
Block *nbp;
|
||||
Icmp *p, *np;
|
||||
uchar ia[IPv4addrlen];
|
||||
|
||||
p = (Icmp *)bp->rp;
|
||||
if(!ip4reply(f, p->src))
|
||||
if(!ip4reply(f, p->src) || !ipv4local(ifc, ia, p->src))
|
||||
return;
|
||||
|
||||
netlog(f, Logicmp, "sending icmpttlexceeded -> %V\n", p->src);
|
||||
netlog(f, Logicmp, "sending icmpttlexceeded %V -> src %V dst %V\n",
|
||||
ia, p->src, p->dst);
|
||||
|
||||
nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
|
||||
nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
|
||||
np = (Icmp *)nbp->rp;
|
||||
np->vihl = IP_VER4;
|
||||
memmove(np->src, ia, sizeof(np->src));
|
||||
memmove(np->dst, p->src, sizeof(np->dst));
|
||||
v6tov4(np->src, ia);
|
||||
memmove(np->data, bp->rp, ICMP_IPSIZE + 8);
|
||||
np->type = TimeExceed;
|
||||
np->code = 0;
|
||||
|
|
|
@ -426,7 +426,7 @@ icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
|
|||
}
|
||||
|
||||
void
|
||||
icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
|
||||
icmphostunr6(Fs *f, Ipifc *ifc, Block *bp, int code, int tome)
|
||||
{
|
||||
int osz = BLEN(bp);
|
||||
int sz = MIN(IPICMPSZ + osz, v6MINTU);
|
||||
|
@ -435,25 +435,18 @@ icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
|
|||
Ip6hdr *p;
|
||||
Proto *icmp = f->t2p[ICMPv6];
|
||||
Icmppriv6 *ipriv = icmp->priv;
|
||||
uchar ia[IPaddrlen];
|
||||
|
||||
p = (Ip6hdr *)bp->rp;
|
||||
if(isv6mcast(p->src) || !ipv6local(ifc, ia, p->src))
|
||||
return;
|
||||
|
||||
if(isv6mcast(p->src))
|
||||
goto freebl;
|
||||
netlog(f, Logicmp, "send icmphostunr %I -> src %I dst %I\n",
|
||||
ia, p->src, p->dst);
|
||||
|
||||
nbp = newIPICMP(sz);
|
||||
np = (IPICMP *)nbp->rp;
|
||||
|
||||
rlock(ifc);
|
||||
if(ipv6local(ifc, np->src, p->src))
|
||||
netlog(f, Logicmp, "send icmphostunr -> src %I dst %I\n", p->src, p->dst);
|
||||
else {
|
||||
netlog(f, Logicmp, "icmphostunr fail -> src %I dst %I\n", p->src, p->dst);
|
||||
runlock(ifc);
|
||||
freeblist(nbp);
|
||||
goto freebl;
|
||||
}
|
||||
|
||||
ipmove(np->src, ia);
|
||||
ipmove(np->dst, p->src);
|
||||
np->type = UnreachableV6;
|
||||
np->code = code;
|
||||
|
@ -463,14 +456,10 @@ icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
|
|||
np->vcf[0] = 0x06 << 4;
|
||||
ipriv->out[UnreachableV6]++;
|
||||
|
||||
if(free)
|
||||
if(tome)
|
||||
ipiput6(f, ifc, nbp);
|
||||
else
|
||||
ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
|
||||
runlock(ifc);
|
||||
freebl:
|
||||
if(free)
|
||||
freeblist(bp);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -483,24 +472,18 @@ icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
|
|||
Ip6hdr *p;
|
||||
Proto *icmp = f->t2p[ICMPv6];
|
||||
Icmppriv6 *ipriv = icmp->priv;
|
||||
uchar ia[IPaddrlen];
|
||||
|
||||
p = (Ip6hdr *)bp->rp;
|
||||
|
||||
if(isv6mcast(p->src))
|
||||
if(isv6mcast(p->src) || !ipv6local(ifc, ia, p->src))
|
||||
return;
|
||||
|
||||
netlog(f, Logicmp, "send icmpttlexceeded6 %I -> src %I dst %I\n",
|
||||
ia, p->src, p->dst);
|
||||
|
||||
nbp = newIPICMP(sz);
|
||||
np = (IPICMP *) nbp->rp;
|
||||
|
||||
if(ipv6local(ifc, np->src, p->src))
|
||||
netlog(f, Logicmp, "send icmpttlexceeded6 -> src %I dst %I\n",
|
||||
p->src, p->dst);
|
||||
else {
|
||||
netlog(f, Logicmp, "icmpttlexceeded6 fail -> src %I dst %I\n",
|
||||
p->src, p->dst);
|
||||
return;
|
||||
}
|
||||
|
||||
ipmove(np->src, ia);
|
||||
ipmove(np->dst, p->src);
|
||||
np->type = TimeExceedV6;
|
||||
np->code = 0;
|
||||
|
@ -522,24 +505,18 @@ icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
|
|||
Ip6hdr *p;
|
||||
Proto *icmp = f->t2p[ICMPv6];
|
||||
Icmppriv6 *ipriv = icmp->priv;
|
||||
uchar ia[IPaddrlen];
|
||||
|
||||
p = (Ip6hdr *)bp->rp;
|
||||
|
||||
if(isv6mcast(p->src))
|
||||
if(isv6mcast(p->src) || !ipv6local(ifc, ia, p->src))
|
||||
return;
|
||||
|
||||
netlog(f, Logicmp, "send icmppkttoobig6 %I -> src %I dst %I\n",
|
||||
ia, p->src, p->dst);
|
||||
|
||||
nbp = newIPICMP(sz);
|
||||
np = (IPICMP *)nbp->rp;
|
||||
|
||||
if(ipv6local(ifc, np->src, p->src))
|
||||
netlog(f, Logicmp, "send icmppkttoobig6 -> src %I dst %I\n",
|
||||
p->src, p->dst);
|
||||
else {
|
||||
netlog(f, Logicmp, "icmppkttoobig6 fail -> src %I dst %I\n",
|
||||
p->src, p->dst);
|
||||
return;
|
||||
}
|
||||
|
||||
ipmove(np->src, ia);
|
||||
ipmove(np->dst, p->src);
|
||||
np->type = PacketTooBigV6;
|
||||
np->code = 0;
|
||||
|
|
|
@ -333,8 +333,7 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
|
|||
if((bp->flag & Bipck) == 0 && ipcsum(&h->vihl)) {
|
||||
ip->stats[InHdrErrors]++;
|
||||
netlog(f, Logip, "ip: checksum error %V\n", h->src);
|
||||
freeblist(bp);
|
||||
return;
|
||||
goto drop;
|
||||
}
|
||||
v4tov6(v6dst, h->dst);
|
||||
notforme = ipforme(f, v6dst) == 0;
|
||||
|
@ -345,8 +344,7 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
|
|||
if(hl < (IP_HLEN4<<2)) {
|
||||
ip->stats[InHdrErrors]++;
|
||||
netlog(f, Logip, "ip: %V bad hivl %ux\n", h->src, h->vihl);
|
||||
freeblist(bp);
|
||||
return;
|
||||
goto drop;
|
||||
}
|
||||
/* If this is not routed strip off the options */
|
||||
if(notforme == 0) {
|
||||
|
@ -364,33 +362,30 @@ ipiput4(Fs *f, Ipifc *ifc, Block *bp)
|
|||
if(notforme) {
|
||||
Route *r;
|
||||
Routehint rh;
|
||||
Ipifc *toifc;
|
||||
|
||||
if(!ip->iprouting){
|
||||
freeblist(bp);
|
||||
return;
|
||||
}
|
||||
if(!ip->iprouting)
|
||||
goto drop;
|
||||
|
||||
/* don't forward to source's network */
|
||||
rh.r = nil;
|
||||
r = v4lookup(f, h->dst, h->src, &rh);
|
||||
if(r == nil || r->ifc == ifc){
|
||||
if(r == nil || (toifc = r->ifc) == nil
|
||||
|| (toifc == ifc && !ifc->reflect)){
|
||||
ip->stats[OutDiscards]++;
|
||||
freeblist(bp);
|
||||
return;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* don't forward if packet has timed out */
|
||||
hop = h->ttl;
|
||||
if(hop < 1) {
|
||||
ip->stats[InHdrErrors]++;
|
||||
icmpttlexceeded(f, ifc->lifc->local, bp);
|
||||
freeblist(bp);
|
||||
return;
|
||||
icmpttlexceeded(f, ifc, bp);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* reassemble if the interface expects it */
|
||||
if(r->ifc == nil) panic("nil route ifc");
|
||||
if(r->ifc->reassemble){
|
||||
if(toifc->reassemble){
|
||||
frag = nhgets(h->frag);
|
||||
if(frag & ~IP_DF) {
|
||||
h->tos = 0;
|
||||
|
@ -434,6 +429,7 @@ if(r->ifc == nil) panic("nil route ifc");
|
|||
}
|
||||
ip->stats[InDiscards]++;
|
||||
ip->stats[InUnknownProtos]++;
|
||||
drop:
|
||||
freeblist(bp);
|
||||
}
|
||||
|
||||
|
|
|
@ -258,7 +258,7 @@ struct Iplifc
|
|||
uchar mask[IPaddrlen];
|
||||
uchar remote[IPaddrlen];
|
||||
uchar net[IPaddrlen];
|
||||
uchar type; /* ruoute type */
|
||||
uchar type; /* route type */
|
||||
uchar tentative; /* =1 => v6 dup disc on, =0 => confirmed unique */
|
||||
uchar onlink; /* =1 => onlink, =0 offlink. */
|
||||
uchar autoflag; /* v6 autonomous flag */
|
||||
|
@ -310,14 +310,11 @@ struct Ipifc
|
|||
int maxtu; /* Maximum transfer unit */
|
||||
int mintu; /* Minumum tranfer unit */
|
||||
void *arg; /* medium specific */
|
||||
int reassemble; /* reassemble IP packets before forwarding */
|
||||
|
||||
/* these are used so that we can unbind on the fly */
|
||||
Lock idlock;
|
||||
uchar reflect; /* allow forwarded packets to go out the same interface */
|
||||
uchar reassemble; /* reassemble IP packets before forwarding to this interface */
|
||||
|
||||
uchar ifcid; /* incremented each 'bind/unbind/add/remove' */
|
||||
int ref; /* number of proc's using this ipifc */
|
||||
Rendez wait; /* where unbinder waits for ref == 0 */
|
||||
int unbinding;
|
||||
|
||||
uchar mac[MAClen]; /* MAC address */
|
||||
|
||||
|
@ -680,7 +677,7 @@ extern char* ipifcadd6(Ipifc *ifc, char**argv, int argc);
|
|||
extern void iprouting(Fs*, int);
|
||||
extern void icmpnoconv(Fs*, Block*);
|
||||
extern void icmpcantfrag(Fs*, Block*, int);
|
||||
extern void icmpttlexceeded(Fs*, uchar*, Block*);
|
||||
extern void icmpttlexceeded(Fs*, Ipifc*, Block*);
|
||||
extern ushort ipcsum(uchar*);
|
||||
extern void ipiput4(Fs*, Ipifc*, Block*);
|
||||
extern void ipiput6(Fs*, Ipifc*, Block*);
|
||||
|
|
|
@ -231,6 +231,8 @@ ipifcunbind(Ipifc *ifc)
|
|||
(*ifc->m->unbind)(ifc);
|
||||
memset(ifc->dev, 0, sizeof(ifc->dev));
|
||||
ifc->arg = nil;
|
||||
|
||||
ifc->reflect = 0;
|
||||
ifc->reassemble = 0;
|
||||
|
||||
/* close queues to stop queuing of packets */
|
||||
|
@ -357,8 +359,8 @@ ipifccreate(Conv *c)
|
|||
error(Enomem);
|
||||
ifc = (Ipifc*)c->ptcl;
|
||||
ifc->conv = c;
|
||||
ifc->unbinding = 0;
|
||||
ifc->m = nil;
|
||||
ifc->reflect = 0;
|
||||
ifc->reassemble = 0;
|
||||
}
|
||||
|
||||
|
@ -764,7 +766,6 @@ static char*
|
|||
ipifcctl(Conv* c, char **argv, int argc)
|
||||
{
|
||||
Ipifc *ifc;
|
||||
int i;
|
||||
|
||||
ifc = (Ipifc*)c->ptcl;
|
||||
if(strcmp(argv[0], "add") == 0)
|
||||
|
@ -777,15 +778,16 @@ ipifcctl(Conv* c, char **argv, int argc)
|
|||
return ipifcunbind(ifc);
|
||||
else if(strcmp(argv[0], "mtu") == 0)
|
||||
return ipifcsetmtu(ifc, argv, argc);
|
||||
else if(strcmp(argv[0], "reassemble") == 0){
|
||||
ifc->reassemble = 1;
|
||||
else if(strcmp(argv[0], "iprouting") == 0){
|
||||
iprouting(c->p->f, argc>1? atoi(argv[1]): 1);
|
||||
return nil;
|
||||
}
|
||||
else if(strcmp(argv[0], "iprouting") == 0){
|
||||
i = 1;
|
||||
if(argc > 1)
|
||||
i = atoi(argv[1]);
|
||||
iprouting(c->p->f, i);
|
||||
else if(strcmp(argv[0], "reflect") == 0){
|
||||
ifc->reflect = argc>1? atoi(argv[1]): 1;
|
||||
return nil;
|
||||
}
|
||||
else if(strcmp(argv[0], "reassemble") == 0){
|
||||
ifc->reassemble = argc>1? atoi(argv[1]): 1;
|
||||
return nil;
|
||||
}
|
||||
else if(strcmp(argv[0], "add6") == 0)
|
||||
|
|
|
@ -116,7 +116,7 @@ ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Routehint *rh)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if(gating && ifc->reassemble <= 0) {
|
||||
if(gating && !ifc->reassemble) {
|
||||
/*
|
||||
* v6 intermediate nodes are not supposed to fragment pkts;
|
||||
* we fragment if ifc->reassemble is turned on; an exception
|
||||
|
@ -248,43 +248,39 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
|
|||
|
||||
if(tentative && h->proto != ICMPv6) {
|
||||
print("tentative addr, drop\n");
|
||||
freeblist(bp);
|
||||
return;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* Check header version */
|
||||
if(BLKIPVER(bp) != IP_VER6) {
|
||||
ip->stats[InHdrErrors]++;
|
||||
netlog(f, Logip, "ip: bad version %ux\n", (h->vcf[0]&0xF0)>>2);
|
||||
freeblist(bp);
|
||||
return;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* route */
|
||||
if(notforme) {
|
||||
Route *r;
|
||||
Routehint rh;
|
||||
Ipifc *toifc;
|
||||
|
||||
if(!ip->iprouting){
|
||||
freeblist(bp);
|
||||
return;
|
||||
}
|
||||
if(!ip->iprouting)
|
||||
goto drop;
|
||||
|
||||
/* don't forward to link-local destinations */
|
||||
if(islinklocal(h->dst) ||
|
||||
(isv6mcast(h->dst) && (h->dst[1]&0xF) <= Link_local_scop)){
|
||||
ip->stats[OutDiscards]++;
|
||||
freeblist(bp);
|
||||
return;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* don't forward to source's network */
|
||||
rh.r = nil;
|
||||
r = v6lookup(f, h->dst, h->src, &rh);
|
||||
if(r == nil || (r->type & Rv4) != 0 || r->ifc == ifc){
|
||||
if(r == nil || (toifc = r->ifc) == nil || (r->type & Rv4) != 0
|
||||
|| (toifc == ifc && !ifc->reflect)){
|
||||
ip->stats[OutDiscards]++;
|
||||
freeblist(bp);
|
||||
return;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* don't forward if packet has timed out */
|
||||
|
@ -292,12 +288,11 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
|
|||
if(hop < 1) {
|
||||
ip->stats[InHdrErrors]++;
|
||||
icmpttlexceeded6(f, ifc, bp);
|
||||
freeblist(bp);
|
||||
return;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
/* process headers & reassemble if the interface expects it */
|
||||
bp = procxtns(ip, bp, r->ifc->reassemble);
|
||||
bp = procxtns(ip, bp, toifc->reassemble);
|
||||
if(bp == nil)
|
||||
return;
|
||||
|
||||
|
@ -325,6 +320,7 @@ ipiput6(Fs *f, Ipifc *ifc, Block *bp)
|
|||
|
||||
ip->stats[InDiscards]++;
|
||||
ip->stats[InUnknownProtos]++;
|
||||
drop:
|
||||
freeblist(bp);
|
||||
}
|
||||
|
||||
|
|
|
@ -185,4 +185,4 @@ void icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac);
|
|||
void icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags);
|
||||
void icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp);
|
||||
void icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp);
|
||||
void icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free);
|
||||
void icmphostunr6(Fs *f, Ipifc *ifc, Block *bp, int code, int tome);
|
||||
|
|
|
@ -404,7 +404,7 @@ udpiput(Proto *udp, Ipifc *ifc, Block *bp)
|
|||
icmpnoconv(f, bp);
|
||||
break;
|
||||
case V6:
|
||||
icmphostunr(f, ifc, bp, Icmp6_port_unreach, 0);
|
||||
icmphostunr6(f, ifc, bp, Icmp6_port_unreach, 0);
|
||||
break;
|
||||
default:
|
||||
panic("udpiput2: version %d", version);
|
||||
|
|
Loading…
Reference in New Issue