plan 9 kernel history: overview | file list | diff list

1998/0310/ip/ipifc.c (diff list | history)

1998/0306/sys/src/9/ip/ipifc.c:23,281998/0307/sys/src/9/ip/ipifc.c:23,29 (short | long)
1998/0306    
Medium *media[] = 
{ 
	ðermedium, 
1998/0307    
	&pktmedium, 
1998/0306    
	&nullmedium, 
	0 
}; 
1998/0306/sys/src/9/ip/ipifc.c:151,1661998/0307/sys/src/9/ip/ipifc.c:152,169
1998/0306    
	} 
	wlock(ifc); 
 
	if(ipifcgrab(ifc) == 0); 
		goto out; 
1998/0307    
	/* dissociate routes */ 
	ifc->ifcid++; 
1998/0306    
 
1998/0307    
	/* disassociate device */ 
	(*ifc->m->unbind)(ifc); 
	memset(ifc->dev, 0, sizeof(ifc->dev)); 
	ifc->arg = nil; 
 
1998/0306    
	/* hangup queues to stop queuing of packets */ 
	qhangup(ifc->conv->rq, "unbind"); 
	qhangup(ifc->conv->wq, "unbind"); 
 
	/* dissociate routes */ 
	ifc->ifcid++; 
                 
	/* disassociate logical interfaces */ 
	av[0] = "remove"; 
	av[1] = ip; 
1998/0306/sys/src/9/ip/ipifc.c:172,1851998/0307/sys/src/9/ip/ipifc.c:175,181
1998/0306    
		ipifcrem(ifc, av, 3, 0); 
	} 
 
	/* disassociate device */ 
	(*ifc->m->unbind)(ifc); 
	memset(ifc->dev, 0, sizeof(ifc->dev)); 
	ifc->arg = nil; 
	ifc->m = &nullmedium; 
	ifc->unbinding = 0; 
                 
out: 
1998/0307    
	ifc->m = nil; 
1998/0306    
	wunlock(ifc); 
	poperror(); 
	return nil; 
1998/0306/sys/src/9/ip/ipifc.c:223,2291998/0307/sys/src/9/ip/ipifc.c:219,225
1998/0306    
	for(lifc = ifc->lifc; lifc; lifc = lifc->next){ 
		m += snprint(state+m, n - m, "%-20.20I ->", lifc->local); 
		for(link = lifc->link; link; link = link->lifclink) 
			m += snprint(state+m, n - m, " %-20.20I", link->local->a); 
1998/0307    
			m += snprint(state+m, n - m, " %-20.20I", link->self->a); 
1998/0306    
		m += snprint(state+m, n - m, "\n"); 
	} 
	runlock(ifc); 
1998/0306/sys/src/9/ip/ipifc.c:272,2771998/0307/sys/src/9/ip/ipifc.c:268,275
1998/0306    
	c->wq = qopen(QMAX, 0, 0, 0); 
	ifc = (Ipifc*)c->ptcl; 
	ifc->conv = c; 
1998/0307    
	ifc->unbinding = 0; 
	ifc->m = nil; 
1998/0306    
} 
 
/*  
1998/0306/sys/src/9/ip/ipifc.c:281,2901998/0307/sys/src/9/ip/ipifc.c:279,291
1998/0306    
static void 
ipifcclose(Conv *c) 
{ 
	/* 
	 *  nothing to do since conversation stays open 
	 *  till the device is unbound. 
	 */ 
1998/0307    
	Ipifc *ifc; 
	Medium *m; 
 
	ifc = (Ipifc*)c->ptcl; 
	m = ifc->m; 
	if(m != nil && m->unbindonclose) 
		ipifcunbind(ifc); 
1998/0306    
	unlock(c); 
} 
 
1998/0306/sys/src/9/ip/ipifc.c:423,4291998/0307/sys/src/9/ip/ipifc.c:424,430
1998/0306    
 
	/* disassociate any addresses */ 
	while(lifc->link) 
		remselfcache(ifc, lifc, lifc->link->local->a); 
1998/0307    
		remselfcache(ifc, lifc, lifc->link->self->a); 
1998/0306    
 
	/* remove the route for this logical interface */ 
	if(isv4(ip)) 
1998/0306/sys/src/9/ip/ipifc.c:456,4611998/0307/sys/src/9/ip/ipifc.c:457,464
1998/0306    
		if(*cp != nil) { 
			ifc = (Ipifc*)(*cp)->ptcl; 
			m = ifc->m; 
1998/0307    
			if(m == nil) 
				continue; 
1998/0306    
			if(m->addroute != nil) 
				m->addroute(ifc, vers, addr, mask, gate, type); 
		} 
1998/0306/sys/src/9/ip/ipifc.c:473,4781998/0307/sys/src/9/ip/ipifc.c:476,483
1998/0306    
		if(*cp != nil) { 
			ifc = (Ipifc*)(*cp)->ptcl; 
			m = ifc->m; 
1998/0307    
			if(m == nil) 
				continue; 
1998/0306    
			if(m->remroute != nil) 
				m->remroute(ifc, vers, addr, mask); 
		} 
1998/0306/sys/src/9/ip/ipifc.c:603,6091998/0307/sys/src/9/ip/ipifc.c:608,614
1998/0306    
	} 
 
	/* look for a link for this lifc */ 
	for(lp = p->link; lp; lp = lp->locallink) 
1998/0307    
	for(lp = p->link; lp; lp = lp->selflink) 
1998/0306    
		if(lp->lifc == lifc) 
			break; 
 
1998/0306/sys/src/9/ip/ipifc.c:612,6191998/0307/sys/src/9/ip/ipifc.c:617,624
1998/0306    
		lp = smalloc(sizeof(*lp)); 
		lp->ref = 1; 
		lp->lifc = lifc; 
		lp->local = p; 
		lp->locallink = p->link; 
1998/0307    
		lp->self = p; 
		lp->selflink = p->link; 
1998/0306    
		p->link = lp; 
		lp->lifclink = lifc->link; 
		lifc->link = lp; 
1998/0306/sys/src/9/ip/ipifc.c:690,6961998/0307/sys/src/9/ip/ipifc.c:695,701
1998/0306    
remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a) 
{ 
	Ipself *p, **l; 
	Iplink *lp, *llp, **ill, **lll; 
1998/0307    
	Iplink *link, **l_self, **l_lifc; 
1998/0306    
 
	qlock(&selftab); 
 
1998/0306/sys/src/9/ip/ipifc.c:709,7221998/0307/sys/src/9/ip/ipifc.c:714,727
1998/0306    
	 *  walk down links from an ifc looking for one 
	 *  that matches the selftab entry 
	 */ 
	ill = &lifc->link; 
	for(lp = *ill; lp; lp = *ill){ 
		if(lp->local == p) 
1998/0307    
	l_lifc = &lifc->link; 
	for(link = *l_lifc; link; link = *l_lifc){ 
		if(link->self == p) 
1998/0306    
			break; 
		ill = &lp->lifclink; 
1998/0307    
		l_lifc = &link->lifclink; 
1998/0306    
	} 
 
	if(lp == nil) 
1998/0307    
	if(link == nil) 
1998/0306    
		goto out; 
 
	/* 
1998/0306/sys/src/9/ip/ipifc.c:723,7391998/0307/sys/src/9/ip/ipifc.c:728,744
1998/0306    
	 *  walk down the links from the selftab looking for 
	 *  the one we just found 
	 */ 
	lll = &p->link; 
	for(llp = *lll; llp; llp = *lll){ 
		if(llp == lp) 
1998/0307    
	l_self = &p->link; 
	for(link = *l_self; link; link = *l_self){ 
		if(link == *(l_lifc)) 
1998/0306    
			break; 
		lll = &lp->locallink; 
1998/0307    
		l_self = &link->selflink; 
1998/0306    
	} 
 
	if(llp == nil) 
1998/0307    
	if(link == nil) 
1998/0306    
		panic("remselfcache"); 
 
	if(--(llp->ref) != 0) 
1998/0307    
	if(--(link->ref) != 0) 
1998/0306    
		goto out; 
 
	if((p->type & Rmulti) && ifc->m->remmulti != nil) 
1998/0306/sys/src/9/ip/ipifc.c:740,7481998/0307/sys/src/9/ip/ipifc.c:745,753
1998/0306    
		(*ifc->m->remmulti)(ifc, a, lifc->local); 
 
	/* ref == 0, remove from both chains and free the link */ 
	*ill = lp->lifclink; 
	*lll = llp->locallink; 
	iplinkfree(lp); 
1998/0307    
	*l_lifc = link->lifclink; 
	*l_self = link->selflink; 
	iplinkfree(link); 
1998/0306    
 
	/* remove from routing table */ 
	if(isv4(a)) 
1998/0306/sys/src/9/ip/ipifc.c:1001,10591998/0307/sys/src/9/ip/ipifc.c:1006,1011
1998/0306    
			return V6; 
	} 
	return 0; 
} 
                 
/* 
 *  used to allow on the fly unbinds, return -1 if interface unusable 
 */ 
int 
ipifccheckin(Ipifc *ifc, Medium *med) 
{ 
	int rv; 
                 
	lock(&ifc->idlock); 
	if(ifc->unbinding || ifc->m != med) 
		rv = -1; 
	else 
		rv = ++(ifc->ref); 
	if(ifc->ref < 0) panic("ipifccheckin"); 
	unlock(&ifc->idlock); 
	return rv; 
} 
                 
void 
ipifccheckout(Ipifc *ifc) 
{ 
	lock(&ifc->idlock); 
	if(--(ifc->ref) == 0) 
	if(ifc->unbinding) 
		wakeup(&ifc->wait); 
	if(ifc->ref < 0) panic("ipifccheckin"); 
	unlock(&ifc->idlock); 
} 
                 
static int 
allout(void *x) 
{ 
	Ipifc *ifc = x; 
                 
	return ifc->ref == 0; 
} 
                 
int 
ipifcgrab(Ipifc *ifc) 
{ 
	lock(&ifc->idlock); 
	if(ifc->unbinding){ 
		unlock(&ifc->idlock); 
		return 0; 
	} 
	ifc->unbinding = 1;		/* after this ref can only go down */ 
	unlock(&ifc->idlock); 
                 
	sleep(&ifc->wait, allout, ifc); 
                 
	return 1; 
} 
 
/* 
1998/0307/sys/src/9/ip/ipifc.c:749,7541998/0310/sys/src/9/ip/ipifc.c:749,757 (short | long)
1998/0307    
	*l_self = link->selflink; 
	iplinkfree(link); 
1998/0306    
 
1998/0310    
	if(p->link != nil) 
		goto out; 
 
1998/0306    
	/* remove from routing table */ 
	if(isv4(a)) 
		v4delroute(a+IPv4off, IPallbits+IPv4off); 
1998/0307/sys/src/9/ip/ipifc.c:755,7631998/0310/sys/src/9/ip/ipifc.c:758,763
1998/0306    
	else 
		v6delroute(a, IPallbits); 
	 
	if(p->link != nil) 
		goto out; 
                 
	/* no more links, remove from hash and free */ 
	*l = p->next; 
	ipselffree(p); 
1998/0307/sys/src/9/ip/ipifc.c:783,7921998/0310/sys/src/9/ip/ipifc.c:783,824
1998/0306    
			continue; 
		count = 0; 
		for(; p != nil && count++ < 6; p = p->next) 
			print("(%i %d %lux)", p->a, p->type, p); 
1998/0310    
			print("(%I %d %lux)", p->a, p->type, p); 
1998/0306    
		print("\n"); 
	} 
	qunlock(&selftab); 
1998/0310    
} 
 
static char *stformat = "%-32.32I %2.2d %4.4s\n"; 
enum 
{ 
	Nstformat= 41, 
}; 
 
long 
ipselftabread(char *cp, ulong offset, int n) 
{ 
	int i, m, nifc; 
	Ipself *p; 
	Iplink *link; 
	char state[8]; 
 
	m = 0; 
	qlock(&selftab); 
	for(i = 0; i < NHASH && m < n; i++){ 
		for(p = selftab.hash[i]; p != nil && m < n; p = p->next){ 
			if(offset == 0){ 
				nifc = 0; 
				for(link = p->link; link; link = link->selflink) 
					nifc++; 
				routetype(p->type, state); 
				m += snprint(cp + m, n - m, stformat, p->a, nifc, state); 
			} 
			offset -= Nstformat; 
		} 
	} 
	qunlock(&selftab); 
	return m; 
1998/0306    
} 
 
 
1998/0310/sys/src/9/ip/ipifc.c:17,301998/0313/sys/src/9/ip/ipifc.c:17,28 (short | long)
1998/0306    
	QMAX		= 64*1024-1, 
}; 
 
	Proto	ipifc; 
extern	Fs	fs; 
                 
Medium *media[] = 
{ 
	ðermedium, 
1998/0307    
	&pktmedium, 
1998/0306    
	&nullmedium, 
1998/0313    
	&tripmedium, 
1998/0306    
	0 
}; 
 
1998/0310/sys/src/9/ip/ipifc.c:43,491998/0313/sys/src/9/ip/ipifc.c:41,46
1998/0306    
	Ipself	*next;		/* free list */ 
}; 
 
typedef struct Ipselftab Ipselftab; 
struct Ipselftab 
{ 
	QLock; 
1998/0310/sys/src/9/ip/ipifc.c:51,571998/0313/sys/src/9/ip/ipifc.c:48,53
1998/0306    
	int	acceptall;	/* true if an interface has the null address */ 
	Ipself	*hash[NHASH];	/* hash chains */ 
}; 
Ipselftab	selftab; 
 
/* 
 *  Multicast addresses are chained onto a Chan so that 
1998/0310/sys/src/9/ip/ipifc.c:70,771998/0313/sys/src/9/ip/ipifc.c:66,73
1998/0306    
 
static char tifc[] = "ifc "; 
 
static void	addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type); 
static void	remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a); 
1998/0313    
static void	addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type); 
static void	remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a); 
1998/0306    
static char*	ipifcjoinmulti(Ipifc *ifc, char **argv, int argc); 
static char*	ipifcleavemulti(Ipifc *ifc, char **argv, int argc); 
 
1998/0310/sys/src/9/ip/ipifc.c:252,2581998/0313/sys/src/9/ip/ipifc.c:248,254
1998/0306    
	if(ifc->m == nil || ifc->m->pktin == nil) 
		freeb(bp); 
	else 
		(*ifc->m->pktin)(ifc, bp); 
1998/0313    
		(*ifc->m->pktin)(c->p->f, ifc, bp); 
1998/0306    
} 
 
/* 
1998/0310/sys/src/9/ip/ipifc.c:299,3051998/0313/sys/src/9/ip/ipifc.c:295,304
1998/0306    
	uchar bcast[IPaddrlen], net[IPaddrlen]; 
	Iplifc *lifc, **l; 
	int i, type, mtu; 
1998/0313    
	Fs *f; 
1998/0306    
 
1998/0313    
	f = ifc->conv->p->f; 
 
1998/0306    
	memset(ip, 0, IPaddrlen); 
	memset(mask, 0, IPaddrlen); 
	memset(rem, 0, IPaddrlen); 
1998/0310/sys/src/9/ip/ipifc.c:359,3821998/0313/sys/src/9/ip/ipifc.c:358,381
1998/0306    
	if(ipcmp(mask, IPallbits) == 0) 
		type |= Rptpt; 
	if(isv4(ip)) 
		v4addroute(tifc, rem+IPv4off, mask+IPv4off, ip+IPv4off, type); 
1998/0313    
		v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, ip+IPv4off, type); 
1998/0306    
	else 
		v6addroute(tifc, ip, mask, rem, type); 
1998/0313    
		v6addroute(f, tifc, ip, mask, rem, type); 
1998/0306    
 
	addselfcache(ifc, lifc, ip, Runi); 
1998/0313    
	addselfcache(f, ifc, lifc, ip, Runi); 
1998/0306    
 
	/* add subnet directed broadcast addresses to the self cache */ 
	for(i = 0; i < IPaddrlen; i++) 
		bcast[i] = (ip[i] & mask[i]) | ~mask[i]; 
	addselfcache(ifc, lifc, bcast, Rbcast); 
1998/0313    
	addselfcache(f, ifc, lifc, bcast, Rbcast); 
1998/0306    
 
	/* add network directed broadcast addresses to the self cache */ 
	memmove(mask, defmask(ip), IPaddrlen); 
	for(i = 0; i < IPaddrlen; i++) 
		bcast[i] = (ip[i] & mask[i]) | ~mask[i]; 
	addselfcache(ifc, lifc, bcast, Rbcast); 
1998/0313    
	addselfcache(f, ifc, lifc, bcast, Rbcast); 
1998/0306    
 
	addselfcache(ifc, lifc, IPv4bcast, Rbcast); 
1998/0313    
	addselfcache(f, ifc, lifc, IPv4bcast, Rbcast); 
1998/0306    
 
out: 
	wunlock(ifc); 
1998/0310/sys/src/9/ip/ipifc.c:394,4031998/0313/sys/src/9/ip/ipifc.c:393,405
1998/0306    
	uchar ip[IPaddrlen]; 
	uchar mask[IPaddrlen]; 
	Iplifc *lifc, **l; 
1998/0313    
	Fs *f; 
1998/0306    
 
	if(argc < 3) 
		return Ebadarg; 
 
1998/0313    
	f = ifc->conv->p->f; 
 
1998/0306    
	parseip(ip, argv[1]); 
	parseipmask(mask, argv[2]); 
 
1998/0310/sys/src/9/ip/ipifc.c:424,4361998/0313/sys/src/9/ip/ipifc.c:426,438
1998/0306    
 
	/* disassociate any addresses */ 
	while(lifc->link) 
1998/0307    
		remselfcache(ifc, lifc, lifc->link->self->a); 
1998/0313    
		remselfcache(f, ifc, lifc, lifc->link->self->a); 
1998/0306    
 
	/* remove the route for this logical interface */ 
	if(isv4(ip)) 
		v4delroute(lifc->remote+IPv4off, lifc->mask+IPv4off); 
1998/0313    
		v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off); 
1998/0306    
	else 
		v6delroute(lifc->remote, lifc->mask); 
1998/0313    
		v6delroute(f, lifc->remote, lifc->mask); 
1998/0306    
 
	free(lifc); 
 
1998/0310/sys/src/9/ip/ipifc.c:447,4591998/0313/sys/src/9/ip/ipifc.c:449,462
1998/0306    
 * TRIP linecards 
 */ 
void 
ipifcaddroute(int vers, uchar *addr, uchar *mask, uchar *gate, int type) 
1998/0313    
ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type) 
1998/0306    
{ 
	Medium *m; 
	Conv **cp; 
1998/0313    
	Conv **cp, **e; 
1998/0306    
	Ipifc *ifc; 
 
	for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ 
1998/0313    
	e = &f->ipifc->conv[f->ipifc->nc]; 
	for(cp = f->ipifc->conv; cp < e; cp++){ 
1998/0306    
		if(*cp != nil) { 
			ifc = (Ipifc*)(*cp)->ptcl; 
			m = ifc->m; 
1998/0310/sys/src/9/ip/ipifc.c:466,4781998/0313/sys/src/9/ip/ipifc.c:469,482
1998/0306    
} 
 
void 
ipifcremroute(int vers, uchar *addr, uchar *mask) 
1998/0313    
ipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask) 
1998/0306    
{ 
	Medium *m; 
	Conv **cp; 
1998/0313    
	Conv **cp, **e; 
1998/0306    
	Ipifc *ifc; 
 
	for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ 
1998/0313    
	e = &f->ipifc->conv[f->ipifc->nc]; 
	for(cp = f->ipifc->conv; cp < e; cp++){ 
1998/0306    
		if(*cp != nil) { 
			ifc = (Ipifc*)(*cp)->ptcl; 
			m = ifc->m; 
1998/0310/sys/src/9/ip/ipifc.c:523,5291998/0313/sys/src/9/ip/ipifc.c:527,533
1998/0306    
	if(err) 
		return err; 
 
	Fsconnected(&fs, c, nil); 
1998/0313    
	Fsconnected(c, nil); 
1998/0306    
 
	return nil; 
} 
1998/0310/sys/src/9/ip/ipifc.c:540,5451998/0313/sys/src/9/ip/ipifc.c:544,551
1998/0306    
	ifc = (Ipifc*)c->ptcl; 
	if(strcmp(argv[0], "add") == 0) 
		return ipifcadd(ifc, argv, argc); 
1998/0313    
 	else if(strcmp(argv[0], "bootp") == 0) 
		return bootp(ifc); 
1998/0306    
	else if(strcmp(argv[0], "remove") == 0) 
		return ipifcrem(ifc, argv, argc, 1); 
	else if(strcmp(argv[0], "unbind") == 0) 
1998/0310/sys/src/9/ip/ipifc.c:551,5781998/0313/sys/src/9/ip/ipifc.c:557,595
1998/0306    
	return "unsupported ctl"; 
} 
 
1998/0313    
ipifcstats(Proto *ipifc, char *buf, int len) 
{ 
	return ipstats(ipifc->f, buf, len); 
} 
 
1998/0306    
void 
ipifcinit(Fs *fs) 
1998/0313    
ipifcinit(Fs *f) 
1998/0306    
{ 
	ipifc.name = "ipifc"; 
	ipifc.kick = ipifckick; 
	ipifc.connect = ipifcconnect; 
	ipifc.announce = nil; 
	ipifc.bind = ipifcbind; 
	ipifc.state = ipifcstate; 
	ipifc.create = ipifccreate; 
	ipifc.close = ipifcclose; 
	ipifc.rcv = nil; 
	ipifc.ctl = ipifcctl; 
	ipifc.advise = nil; 
	ipifc.stats = ipstats; 
	ipifc.inuse = ipifcinuse; 
	ipifc.local = ipifclocal; 
	ipifc.ipproto = -1; 
	ipifc.nc = Maxmedia; 
	ipifc.ptclsize = sizeof(Ipifc); 
1998/0313    
	Proto *ipifc; 
1998/0306    
 
	Fsproto(fs, &ipifc); 
1998/0313    
	ipifc = smalloc(sizeof(Ipifc)); 
	ipifc->name = "ipifc"; 
	ipifc->kick = ipifckick; 
	ipifc->connect = ipifcconnect; 
	ipifc->announce = nil; 
	ipifc->bind = ipifcbind; 
	ipifc->state = ipifcstate; 
	ipifc->create = ipifccreate; 
	ipifc->close = ipifcclose; 
	ipifc->rcv = nil; 
	ipifc->ctl = ipifcctl; 
	ipifc->advise = nil; 
	ipifc->stats = ipifcstats; 
	ipifc->inuse = ipifcinuse; 
	ipifc->local = ipifclocal; 
	ipifc->ipproto = -1; 
	ipifc->nc = Maxmedia; 
	ipifc->ptclsize = sizeof(Ipifc); 
 
	f->ipifc = ipifc;			/* hack for ipifcremroute, findipifc, ... */ 
	f->self = smalloc(sizeof(Ipselftab));	/* hack for ipforme */ 
 
	Fsproto(f, ipifc); 
1998/0306    
} 
 
/* 
1998/0310/sys/src/9/ip/ipifc.c:580,5961998/0313/sys/src/9/ip/ipifc.c:597,613
1998/0306    
 *	called with c->car locked 
 */ 
static void 
addselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a, int type) 
1998/0313    
addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type) 
1998/0306    
{ 
	Ipself *p; 
	Iplink *lp; 
	int h; 
 
	qlock(&selftab); 
1998/0313    
	qlock(f->self); 
1998/0306    
 
	/* see if the address already exists */ 
	h = hashipa(a); 
	for(p = selftab.hash[h]; p; p = p->next) 
1998/0313    
	for(p = f->self->hash[h]; p; p = p->next) 
1998/0306    
		if(memcmp(a, p->a, IPaddrlen) == 0) 
			break; 
 
1998/0310/sys/src/9/ip/ipifc.c:599,6101998/0313/sys/src/9/ip/ipifc.c:616,627
1998/0306    
		p = smalloc(sizeof(*p)); 
		ipmove(p->a, a); 
		p->type = type; 
		p->next = selftab.hash[h]; 
		selftab.hash[h] = p; 
1998/0313    
		p->next = f->self->hash[h]; 
		f->self->hash[h] = p; 
1998/0306    
 
		/* if the null address, accept all packets */ 
		if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0) 
			selftab.acceptall = 1; 
1998/0313    
			f->self->acceptall = 1; 
1998/0306    
	} 
 
	/* look for a link for this lifc */ 
1998/0310/sys/src/9/ip/ipifc.c:625,6331998/0313/sys/src/9/ip/ipifc.c:642,650
1998/0306    
 
		/* add to routing table */ 
		if(isv4(a)) 
			v4addroute(tifc, a+IPv4off, IPallbits+IPv4off, a+IPv4off, type); 
1998/0313    
			v4addroute(f, tifc, a+IPv4off, IPallbits+IPv4off, a+IPv4off, type); 
1998/0306    
		else 
			v6addroute(tifc, a, IPallbits, a, type); 
1998/0313    
			v6addroute(f, tifc, a, IPallbits, a, type); 
1998/0306    
 
		if((type & Rmulti) && ifc->m->addmulti != nil) 
			(*ifc->m->addmulti)(ifc, a, lifc->local); 
1998/0310/sys/src/9/ip/ipifc.c:635,6411998/0313/sys/src/9/ip/ipifc.c:652,658
1998/0306    
		lp->ref++; 
	} 
 
	qunlock(&selftab); 
1998/0313    
	qunlock(f->self); 
1998/0306    
} 
 
/* 
1998/0310/sys/src/9/ip/ipifc.c:642,6481998/0313/sys/src/9/ip/ipifc.c:659,665
1998/0306    
 *  These structures are unlinked from their chains while 
 *  other threads may be using them.  To avoid excessive locking, 
 *  just put them aside for a while before freeing them. 
 *	called with &selftab locked 
1998/0313    
 *	called with f->self locked 
1998/0306    
 */ 
static Iplink *freeiplink; 
static Ipself *freeipself; 
1998/0310/sys/src/9/ip/ipifc.c:692,7061998/0313/sys/src/9/ip/ipifc.c:709,723
1998/0306    
 *	called with c->car locked 
 */ 
static void 
remselfcache(Ipifc *ifc, Iplifc *lifc, uchar *a) 
1998/0313    
remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a) 
1998/0306    
{ 
	Ipself *p, **l; 
1998/0307    
	Iplink *link, **l_self, **l_lifc; 
1998/0306    
 
	qlock(&selftab); 
1998/0313    
	qlock(f->self); 
1998/0306    
 
	/* find the unique selftab entry */ 
	l = &selftab.hash[hashipa(a)]; 
1998/0313    
	l = &f->self->hash[hashipa(a)]; 
1998/0306    
	for(p = *l; p; p = *l){ 
		if(ipcmp(p->a, a) == 0) 
			break; 
1998/0310/sys/src/9/ip/ipifc.c:754,7621998/0313/sys/src/9/ip/ipifc.c:771,779
1998/0310    
 
1998/0306    
	/* remove from routing table */ 
	if(isv4(a)) 
		v4delroute(a+IPv4off, IPallbits+IPv4off); 
1998/0313    
		v4delroute(f, a+IPv4off, IPallbits+IPv4off); 
1998/0306    
	else 
		v6delroute(a, IPallbits); 
1998/0313    
		v6delroute(f, a, IPallbits); 
1998/0306    
	 
	/* no more links, remove from hash and free */ 
	*l = p->next; 
1998/0310/sys/src/9/ip/ipifc.c:764,7941998/0313/sys/src/9/ip/ipifc.c:781,792
1998/0306    
 
	/* if IPnoaddr, forget */ 
	if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0) 
		selftab.acceptall = 0; 
1998/0313    
		f->self->acceptall = 0; 
1998/0306    
 
out: 
	qunlock(&selftab); 
1998/0313    
	qunlock(f->self); 
1998/0306    
} 
 
static void 
dumpselftab(void) 
{ 
	int i, count; 
	Ipself *p; 
                 
	qlock(&selftab); 
	for(i = 0; i < NHASH; i++){ 
		p = selftab.hash[i]; 
		if(p == nil) 
			continue; 
		count = 0; 
		for(; p != nil && count++ < 6; p = p->next) 
1998/0310    
			print("(%I %d %lux)", p->a, p->type, p); 
1998/0306    
		print("\n"); 
	} 
	qunlock(&selftab); 
1998/0310    
} 
                 
static char *stformat = "%-32.32I %2.2d %4.4s\n"; 
enum 
{ 
1998/0310/sys/src/9/ip/ipifc.c:796,8021998/0313/sys/src/9/ip/ipifc.c:794,800
1998/0310    
}; 
 
long 
ipselftabread(char *cp, ulong offset, int n) 
1998/0313    
ipselftabread(Fs *f, char *cp, ulong offset, int n) 
1998/0310    
{ 
	int i, m, nifc; 
	Ipself *p; 
1998/0310/sys/src/9/ip/ipifc.c:804,8121998/0313/sys/src/9/ip/ipifc.c:802,810
1998/0310    
	char state[8]; 
 
	m = 0; 
	qlock(&selftab); 
1998/0313    
	qlock(f->self); 
1998/0310    
	for(i = 0; i < NHASH && m < n; i++){ 
		for(p = selftab.hash[i]; p != nil && m < n; p = p->next){ 
1998/0313    
		for(p = f->self->hash[i]; p != nil && m < n; p = p->next){ 
1998/0310    
			if(offset == 0){ 
				nifc = 0; 
				for(link = p->link; link; link = link->selflink) 
1998/0310/sys/src/9/ip/ipifc.c:817,8231998/0313/sys/src/9/ip/ipifc.c:815,821
1998/0310    
			offset -= Nstformat; 
		} 
	} 
	qunlock(&selftab); 
1998/0313    
	qunlock(f->self); 
1998/0310    
	return m; 
1998/0306    
} 
 
1998/0310/sys/src/9/ip/ipifc.c:830,8531998/0313/sys/src/9/ip/ipifc.c:828,845
1998/0306    
 *	Rmcast 
 */ 
int 
ipforme(uchar *addr) 
1998/0313    
ipforme(Fs *f, uchar *addr) 
1998/0306    
{ 
	Ipself *p; 
	int count; 
 
	p = selftab.hash[hashipa(addr)]; 
	count = 0; 
1998/0313    
	p = f->self->hash[hashipa(addr)]; 
1998/0306    
	for(; p; p = p->next){ 
		if(count++ > 1000){	/* check for loops */ 
			dumpselftab(); 
			break; 
		} 
		if(ipcmp(addr, p->a) == 0) 
			return p->type; 
	} 
 
	/* hack to say accept anything */ 
	if(selftab.acceptall) 
1998/0313    
	if(f->self->acceptall) 
1998/0306    
		return Runi; 
 
	return 0; 
1998/0310/sys/src/9/ip/ipifc.c:858,8861998/0313/sys/src/9/ip/ipifc.c:850,877
1998/0306    
 *  return nil. 
 */ 
Ipifc* 
findipifc(uchar *remote, int type) 
1998/0313    
findipifc(Fs *f, uchar *remote, int type) 
1998/0306    
{ 
	Ipifc *ifc; 
	Iplifc *lifc; 
	Conv **cp; 
1998/0313    
	Conv **cp, **e; 
1998/0306    
	uchar gnet[IPaddrlen]; 
 
	for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ 
1998/0313    
	e = &f->ipifc->conv[f->ipifc->nc]; 
	for(cp = f->ipifc->conv; cp < e; cp++){ 
1998/0306    
		if(*cp == 0) 
			continue; 
		ifc = (Ipifc*)(*cp)->ptcl; 
		for(lifc = ifc->lifc; lifc; lifc = lifc->next){ 
			maskip(remote, lifc->mask, gnet); 
			if(ipcmp(gnet, lifc->net) == 0){ 
				qunlock(&ipifc); 
1998/0313    
			if(ipcmp(gnet, lifc->net) == 0) 
1998/0306    
				return ifc; 
			} 
		} 
	} 
 
	/* for now for broadcast and mutlicast, just use first interface */ 
	if(type & (Rbcast|Rmulti)){ 
		for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ 
1998/0313    
		for(cp = f->ipifc->conv; cp < e; cp++){ 
1998/0306    
			if(*cp == 0) 
				continue; 
			ifc = (Ipifc*)(*cp)->ptcl; 
1998/0310/sys/src/9/ip/ipifc.c:897,9131998/0313/sys/src/9/ip/ipifc.c:888,904
1998/0306    
 *  local and return the ifc for that address 
 */ 
void 
findlocalip(uchar *local, uchar *remote) 
1998/0313    
findlocalip(Fs *f, uchar *local, uchar *remote) 
1998/0306    
{ 
	Ipifc *ifc; 
	Iplifc *lifc; 
	Conv **cp; 
1998/0313    
	Conv **cp, **e; 
1998/0306    
	Route *r; 
	uchar gate[IPaddrlen]; 
	uchar gnet[IPaddrlen]; 
 
	qlock(&ipifc); 
	r = v6lookup(remote); 
1998/0313    
	qlock(f->ipifc); 
	r = v6lookup(f, remote); 
1998/0306    
	 
	if(r != nil){ 
		ifc = r->ifc; 
1998/0310/sys/src/9/ip/ipifc.c:932,9381998/0313/sys/src/9/ip/ipifc.c:923,930
1998/0306    
	} 
		 
	/* no match, choose first ifc local address */ 
	for(cp = ipifc.conv; cp < &ipifc.conv[ipifc.nc]; cp++){ 
1998/0313    
	e = &f->ipifc->conv[f->ipifc->nc]; 
	for(cp = f->ipifc->conv; cp < e; cp++){ 
1998/0306    
		if(*cp == 0) 
			continue; 
		ifc = (Ipifc*)(*cp)->ptcl; 
1998/0310/sys/src/9/ip/ipifc.c:943,9491998/0313/sys/src/9/ip/ipifc.c:935,941
1998/0306    
	} 
 
out: 
	qunlock(&ipifc); 
1998/0313    
	qunlock(f->ipifc); 
1998/0306    
} 
 
/* 
1998/0310/sys/src/9/ip/ipifc.c:999,10051998/0313/sys/src/9/ip/ipifc.c:991,997
1998/0306    
 *  See if we're proxying for this address on this interface 
 */ 
int 
ipproxyifc(Ipifc *ifc, uchar *ip) 
1998/0313    
ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip) 
1998/0306    
{ 
	Route *r; 
	uchar net[IPaddrlen]; 
1998/0310/sys/src/9/ip/ipifc.c:1006,10121998/0313/sys/src/9/ip/ipifc.c:998,1004
1998/0306    
	Iplifc *lifc; 
 
	/* see if this is a direct connected pt to pt address */ 
	r = v6lookup(ip); 
1998/0313    
	r = v6lookup(f, ip); 
1998/0306    
	if(r == nil) 
		return 0; 
	if((r->type & Rifc) == 0) 
1998/0310/sys/src/9/ip/ipifc.c:1050,10551998/0313/sys/src/9/ip/ipifc.c:1042,1050
1998/0306    
	Iplifc *lifc; 
	Conv **p; 
	Ipmulti *multi, **l; 
1998/0313    
	Fs *f; 
 
	f = c->p->f; 
1998/0306    
	 
	for(l = &c->multi; *l; l = &(*l)->next) 
		if(ipcmp(ma, (*l)->ma) == 0) 
1998/0310/sys/src/9/ip/ipifc.c:1061,10671998/0313/sys/src/9/ip/ipifc.c:1056,1062
1998/0306    
	ipmove(multi->ia, ia); 
	multi->next = nil; 
 
	for(p = ipifc.conv; *p; p++){ 
1998/0313    
	for(p = f->ipifc->conv; *p; p++){ 
1998/0306    
		if((*p)->inuse == 0) 
			continue; 
		ifc = (Ipifc*)(*p)->ptcl; 
1998/0310/sys/src/9/ip/ipifc.c:1072,10781998/0313/sys/src/9/ip/ipifc.c:1067,1073
1998/0306    
		wlock(ifc); 
		for(lifc = ifc->lifc; lifc; lifc = lifc->next) 
			if(ipcmp(ia, lifc->local) == 0) 
				addselfcache(ifc, lifc, ma, Rmulti); 
1998/0313    
				addselfcache(f, ifc, lifc, ma, Rmulti); 
1998/0306    
		wunlock(ifc); 
		poperror(); 
	} 
1998/0310/sys/src/9/ip/ipifc.c:1089,10941998/0313/sys/src/9/ip/ipifc.c:1084,1092
1998/0306    
	Iplifc *lifc; 
	Conv **p; 
	Ipifc *ifc; 
1998/0313    
	Fs *f; 
 
	f = c->p->f; 
1998/0306    
	 
	for(l = &c->multi; *l; l = &(*l)->next) 
		if(ipcmp(ma, (*l)->ma) == 0) 
1998/0310/sys/src/9/ip/ipifc.c:1101,11071998/0313/sys/src/9/ip/ipifc.c:1099,1105
1998/0306    
 
	*l = multi->next; 
 
	for(p = ipifc.conv; *p; p++){ 
1998/0313    
	for(p = f->ipifc->conv; *p; p++){ 
1998/0306    
		if((*p)->inuse == 0) 
			continue; 
 
1998/0310/sys/src/9/ip/ipifc.c:1113,11191998/0313/sys/src/9/ip/ipifc.c:1111,1117
1998/0306    
		wlock(ifc); 
		for(lifc = ifc->lifc; lifc; lifc = lifc->next) 
			if(ipcmp(ia, lifc->local) == 0) 
				remselfcache(ifc, lifc, ma); 
1998/0313    
				remselfcache(f, ifc, lifc, ma); 
1998/0306    
		wunlock(ifc); 
		poperror(); 
	} 
1998/0313/sys/src/9/ip/ipifc.c:540,5451998/0314/sys/src/9/ip/ipifc.c:540,546 (short | long)
1998/0306    
ipifcctl(Conv* c, char**argv, int argc) 
{ 
	Ipifc *ifc; 
1998/0314    
	int i; 
1998/0306    
 
	ifc = (Ipifc*)c->ptcl; 
	if(strcmp(argv[0], "add") == 0) 
1998/0313/sys/src/9/ip/ipifc.c:554,5591998/0314/sys/src/9/ip/ipifc.c:555,567
1998/0306    
		return ipifcjoinmulti(ifc, argv, argc); 
	else if(strcmp(argv[0], "leavemulti") == 0) 
		return ipifcleavemulti(ifc, argv, argc); 
1998/0314    
	else if(strcmp(argv[0], "iprouting") == 0){ 
		i = 1; 
		if(argc > 1) 
			i = atoi(argv[1]); 
		iprouting(c->p->f, i); 
		return nil; 
	} 
1998/0306    
	return "unsupported ctl"; 
} 
 
1998/0314/sys/src/9/ip/ipifc.c:360,3661998/0316/sys/src/9/ip/ipifc.c:360,366 (short | long)
1998/0306    
	if(isv4(ip)) 
1998/0313    
		v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, ip+IPv4off, type); 
1998/0306    
	else 
1998/0313    
		v6addroute(f, tifc, ip, mask, rem, type); 
1998/0316    
		v6addroute(f, tifc, rem, mask, ip, type); 
1998/0306    
 
1998/0313    
	addselfcache(f, ifc, lifc, ip, Runi); 
1998/0306    
 
1998/0314/sys/src/9/ip/ipifc.c:860,8701998/0316/sys/src/9/ip/ipifc.c:860,874
1998/0306    
Ipifc* 
1998/0313    
findipifc(Fs *f, uchar *remote, int type) 
1998/0306    
{ 
	Ipifc *ifc; 
1998/0316    
	Ipifc *ifc, *x; 
1998/0306    
	Iplifc *lifc; 
1998/0313    
	Conv **cp, **e; 
1998/0306    
	uchar gnet[IPaddrlen]; 
1998/0316    
	uchar xmask[IPaddrlen]; 
1998/0306    
 
1998/0316    
	x = nil; 
 
	/* find most specific match */ 
1998/0313    
	e = &f->ipifc->conv[f->ipifc->nc]; 
	for(cp = f->ipifc->conv; cp < e; cp++){ 
1998/0306    
		if(*cp == 0) 
1998/0314/sys/src/9/ip/ipifc.c:872,8831998/0316/sys/src/9/ip/ipifc.c:876,893
1998/0306    
		ifc = (Ipifc*)(*cp)->ptcl; 
		for(lifc = ifc->lifc; lifc; lifc = lifc->next){ 
			maskip(remote, lifc->mask, gnet); 
1998/0313    
			if(ipcmp(gnet, lifc->net) == 0) 
1998/0306    
				return ifc; 
1998/0316    
			if(ipcmp(gnet, lifc->net) == 0){ 
				if(x == nil || ipcmp(lifc->mask, xmask) > 0){ 
					x = ifc; 
					ipmove(xmask, lifc->mask); 
				} 
			} 
1998/0306    
		} 
	} 
1998/0316    
	if(x != nil) 
		return x; 
1998/0306    
 
	/* for now for broadcast and mutlicast, just use first interface */ 
1998/0316    
	/* for now for broadcast and multicast, just use first interface */ 
1998/0306    
	if(type & (Rbcast|Rmulti)){ 
1998/0313    
		for(cp = f->ipifc->conv; cp < e; cp++){ 
1998/0306    
			if(*cp == 0) 
1998/0316/sys/src/9/ip/ipifc.c:369,3781998/0318/sys/src/9/ip/ipifc.c:369,389 (short | long)
Add subnet- and network-directed broadcast addresses to self cache.
Note bizarre computation of broadcast.
rsc Fri Mar 4 12:44:25 2005
1998/0306    
		bcast[i] = (ip[i] & mask[i]) | ~mask[i]; 
1998/0313    
	addselfcache(f, ifc, lifc, bcast, Rbcast); 
1998/0306    
 
1998/0318    
	/* add old subnet directed broadcast addresses to the self cache */ 
	for(i = 0; i < IPaddrlen; i++) 
		bcast[i] = (ip[i] & mask[i]) & mask[i]; 
	addselfcache(f, ifc, lifc, bcast, Rbcast); 
 
1998/0306    
	/* add network directed broadcast addresses to the self cache */ 
	memmove(mask, defmask(ip), IPaddrlen); 
	for(i = 0; i < IPaddrlen; i++) 
		bcast[i] = (ip[i] & mask[i]) | ~mask[i]; 
1998/0318    
	addselfcache(f, ifc, lifc, bcast, Rbcast); 
 
	/* add old network directed broadcast addresses to the self cache */ 
	memmove(mask, defmask(ip), IPaddrlen); 
	for(i = 0; i < IPaddrlen; i++) 
		bcast[i] = (ip[i] & mask[i]) & mask[i]; 
1998/0313    
	addselfcache(f, ifc, lifc, bcast, Rbcast); 
1998/0306    
 
1998/0313    
	addselfcache(f, ifc, lifc, IPv4bcast, Rbcast); 
1998/0318/sys/src/9/ip/ipifc.c:286,2911998/0330/sys/src/9/ip/ipifc.c:286,310 (short | long)
Add ipifcsetmtu and mtu control message.
rsc Fri Mar 4 12:44:25 2005
1998/0306    
} 
 
/* 
1998/0330    
 *  change an interface's mtu 
 */ 
char* 
ipifcsetmtu(Ipifc *ifc, char **argv, int argc) 
{ 
	int mtu; 
 
	if(argc < 2) 
		return Ebadarg; 
	if(ifc->m == nil) 
		return Ebadarg; 
	mtu = strtoul(argv[1], 0, 0); 
	if(mtu < ifc->m->minmtu || mtu > ifc->m->maxmtu) 
		return Ebadarg; 
	ifc->maxmtu = mtu; 
	return nil; 
} 
 
/* 
1998/0306    
 *  add an address to an interface. 
 */ 
char* 
1998/0318/sys/src/9/ip/ipifc.c:566,5711998/0330/sys/src/9/ip/ipifc.c:585,592
1998/0306    
		return ipifcjoinmulti(ifc, argv, argc); 
	else if(strcmp(argv[0], "leavemulti") == 0) 
		return ipifcleavemulti(ifc, argv, argc); 
1998/0330    
	else if(strcmp(argv[0], "mtu") == 0) 
		return ipifcsetmtu(ifc, argv, argc); 
1998/0314    
	else if(strcmp(argv[0], "iprouting") == 0){ 
		i = 1; 
		if(argc > 1) 
1998/0330/sys/src/9/ip/ipifc.c:17,281998/0423/sys/src/9/ip/ipifc.c:17,24 (short | long)
Add addipmedium to avoid hard-coded list of media.
rsc Fri Mar 4 12:44:25 2005
1998/0306    
	QMAX		= 64*1024-1, 
}; 
 
Medium *media[] = 
1998/0423    
Medium *media[32] = 
1998/0306    
{ 
	ðermedium, 
1998/0307    
	&pktmedium, 
1998/0306    
	&nullmedium, 
1998/0313    
	&tripmedium, 
1998/0306    
	0 
}; 
 
1998/0330/sys/src/9/ip/ipifc.c:70,751998/0423/sys/src/9/ip/ipifc.c:66,86
1998/0313    
static void	remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a); 
1998/0306    
static char*	ipifcjoinmulti(Ipifc *ifc, char **argv, int argc); 
static char*	ipifcleavemulti(Ipifc *ifc, char **argv, int argc); 
1998/0423    
 
/* 
 *  link in a new medium 
 */ 
void 
addipmedium(Medium *med) 
{ 
	int i; 
 
	for(i = 0; i < nelem(media)-1; i++) 
		if(media[i] == nil){ 
			media[i] = med; 
			break; 
		} 
} 
1998/0306    
 
/* 
 *  find the medium with this name 
1998/0423/sys/src/9/ip/ipifc.c:135,1401998/0507/sys/src/9/ip/ipifc.c:135,141 (short | long)
1998/0306    
	ifc->m = m; 
	ifc->minmtu = ifc->m->minmtu; 
	ifc->maxmtu = ifc->m->maxmtu; 
1998/0507    
	ifc->conv->inuse++; 
1998/0306    
	ifc->ifcid++; 
 
	wunlock(ifc); 
1998/0423/sys/src/9/ip/ipifc.c:160,1651998/0507/sys/src/9/ip/ipifc.c:161,167
1998/0306    
	wlock(ifc); 
 
1998/0307    
	/* dissociate routes */ 
1998/0507    
	ifc->conv->inuse--; 
1998/0307    
	ifc->ifcid++; 
1998/0306    
 
1998/0307    
	/* disassociate device */ 
1998/0507/sys/src/9/ip/ipifc.c:165,1711998/0515/sys/src/9/ip/ipifc.c:165,172 (short | long)
1998/0307    
	ifc->ifcid++; 
1998/0306    
 
1998/0307    
	/* disassociate device */ 
	(*ifc->m->unbind)(ifc); 
1998/0515    
	if(ifc->m) 
		(*ifc->m->unbind)(ifc); 
1998/0307    
	memset(ifc->dev, 0, sizeof(ifc->dev)); 
	ifc->arg = nil; 
 
1998/0507/sys/src/9/ip/ipifc.c:293,2991998/0515/sys/src/9/ip/ipifc.c:294,300
1998/0307    
 
	ifc = (Ipifc*)c->ptcl; 
	m = ifc->m; 
	if(m != nil && m->unbindonclose) 
1998/0515    
	if(m == nil || m->unbindonclose) 
1998/0307    
		ipifcunbind(ifc); 
1998/0306    
	unlock(c); 
} 
1998/0515/sys/src/9/ip/ipifc.c:135,1411998/0516/sys/src/9/ip/ipifc.c:135,145 (short | long)
1998/0306    
	ifc->m = m; 
	ifc->minmtu = ifc->m->minmtu; 
	ifc->maxmtu = ifc->m->maxmtu; 
1998/0507    
	ifc->conv->inuse++; 
1998/0516    
	if(ifc->m->unbindonclose == 0){ 
		lock(ifc->conv); 
		ifc->conv->inuse++; 
		unlock(ifc->conv); 
	} 
1998/0306    
	ifc->ifcid++; 
 
	wunlock(ifc); 
1998/0515/sys/src/9/ip/ipifc.c:161,1711998/0516/sys/src/9/ip/ipifc.c:165,179
1998/0306    
	wlock(ifc); 
 
1998/0307    
	/* dissociate routes */ 
1998/0507    
	ifc->conv->inuse--; 
1998/0516    
	if(ifc->m != nil && ifc->m->unbindonclose == 0){ 
		lock(ifc->conv); 
		ifc->conv->inuse--; 
		unlock(ifc->conv); 
	} 
1998/0307    
	ifc->ifcid++; 
1998/0306    
 
1998/0307    
	/* disassociate device */ 
1998/0515    
	if(ifc->m) 
1998/0516    
	if(ifc->m != nil && ifc->m->unbind) 
1998/0515    
		(*ifc->m->unbind)(ifc); 
1998/0307    
	memset(ifc->dev, 0, sizeof(ifc->dev)); 
	ifc->arg = nil; 
1998/0515/sys/src/9/ip/ipifc.c:188,1931998/0516/sys/src/9/ip/ipifc.c:196,202
1998/0307    
	ifc->m = nil; 
1998/0306    
	wunlock(ifc); 
	poperror(); 
1998/0516    
 
1998/0306    
	return nil; 
} 
 
1998/0515/sys/src/9/ip/ipifc.c:294,3001998/0516/sys/src/9/ip/ipifc.c:303,309
1998/0307    
 
	ifc = (Ipifc*)c->ptcl; 
	m = ifc->m; 
1998/0515    
	if(m == nil || m->unbindonclose) 
1998/0516    
	if(m != nil && m->unbindonclose) 
1998/0307    
		ipifcunbind(ifc); 
1998/0306    
	unlock(c); 
} 
1998/0516/sys/src/9/ip/ipifc.c:135,1451998/0630/sys/src/9/ip/ipifc.c:135,141 (short | long)
1998/0306    
	ifc->m = m; 
	ifc->minmtu = ifc->m->minmtu; 
	ifc->maxmtu = ifc->m->maxmtu; 
1998/0516    
	if(ifc->m->unbindonclose == 0){ 
		lock(ifc->conv); 
		ifc->conv->inuse++; 
		unlock(ifc->conv); 
	} 
1998/0630    
	ifc->conv->inuse++; 
1998/0306    
	ifc->ifcid++; 
 
	wunlock(ifc); 
1998/0516/sys/src/9/ip/ipifc.c:165,1801998/0630/sys/src/9/ip/ipifc.c:161,171
1998/0306    
	wlock(ifc); 
 
1998/0307    
	/* dissociate routes */ 
1998/0516    
	if(ifc->m != nil && ifc->m->unbindonclose == 0){ 
		lock(ifc->conv); 
		ifc->conv->inuse--; 
		unlock(ifc->conv); 
	} 
1998/0630    
	ifc->conv->inuse--; 
1998/0307    
	ifc->ifcid++; 
1998/0306    
 
1998/0307    
	/* disassociate device */ 
1998/0516    
	if(ifc->m != nil && ifc->m->unbind) 
1998/0515    
		(*ifc->m->unbind)(ifc); 
1998/0630    
	(*ifc->m->unbind)(ifc); 
1998/0307    
	memset(ifc->dev, 0, sizeof(ifc->dev)); 
	ifc->arg = nil; 
 
1998/0516/sys/src/9/ip/ipifc.c:196,2021998/0630/sys/src/9/ip/ipifc.c:187,192
1998/0307    
	ifc->m = nil; 
1998/0306    
	wunlock(ifc); 
	poperror(); 
1998/0516    
                 
1998/0306    
	return nil; 
} 
 
1998/0516/sys/src/9/ip/ipifc.c:209,2231998/0630/sys/src/9/ip/ipifc.c:199,213
1998/0306    
 
	ifc = (Ipifc*)c->ptcl; 
 
	m = snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu); 
                 
	rlock(ifc); 
	for(lifc = ifc->lifc; lifc; lifc = lifc->next) 
1998/0630    
	m = 0; 
	for(lifc = ifc->lifc; lifc; lifc = lifc->next) { 
		m += snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu); 
1998/0306    
		m += snprint(state+m, n - m, 
			" %-20.20I %-20.20M %-20.20I %-7d %-7d %-7d %-7d", 
1998/0630    
			" %-20.20I %-20.20M %-20.20I %-7d %-7d %-7d %-7d\n", 
1998/0306    
				lifc->local, lifc->mask, lifc->remote, 
				ifc->in, ifc->out, ifc->inerr, ifc->outerr); 
	m += snprint(state+m, n - m, "\n"); 
1998/0630    
	} 
1998/0306    
	runlock(ifc); 
	return m; 
} 
1998/0516/sys/src/9/ip/ipifc.c:483,4911998/0630/sys/src/9/ip/ipifc.c:473,481
1998/0306    
 
	/* remove the route for this logical interface */ 
	if(isv4(ip)) 
1998/0313    
		v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off); 
1998/0630    
		v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off, 1); 
1998/0306    
	else 
1998/0313    
		v6delroute(f, lifc->remote, lifc->mask); 
1998/0630    
		v6delroute(f, lifc->remote, lifc->mask, 1); 
1998/0306    
 
	free(lifc); 
 
1998/0516/sys/src/9/ip/ipifc.c:834,8421998/0630/sys/src/9/ip/ipifc.c:824,832
1998/0310    
 
1998/0306    
	/* remove from routing table */ 
	if(isv4(a)) 
1998/0313    
		v4delroute(f, a+IPv4off, IPallbits+IPv4off); 
1998/0630    
		v4delroute(f, a+IPv4off, IPallbits+IPv4off, 1); 
1998/0306    
	else 
1998/0313    
		v6delroute(f, a, IPallbits); 
1998/0630    
		v6delroute(f, a, IPallbits, 1); 
1998/0306    
	 
	/* no more links, remove from hash and free */ 
	*l = p->next; 
1998/0630/sys/src/9/ip/ipifc.c:329,3341998/0702/sys/src/9/ip/ipifc.c:329,337 (short | long)
1998/0306    
	int i, type, mtu; 
1998/0313    
	Fs *f; 
1998/0306    
 
1998/0702    
	if(ifc->m == nil) 
		return "ipifc not yet bound to device"; 
 
1998/0313    
	f = ifc->conv->p->f; 
 
1998/0306    
	memset(ip, 0, IPaddrlen); 
1998/0702/sys/src/9/ip/ipifc.c:135,1411998/0709/sys/src/9/ip/ipifc.c:135,145 (short | long)
1998/0306    
	ifc->m = m; 
	ifc->minmtu = ifc->m->minmtu; 
	ifc->maxmtu = ifc->m->maxmtu; 
1998/0630    
	ifc->conv->inuse++; 
1998/0709    
	if(ifc->m->unbindonclose == 0){ 
		lock(ifc->conv); 
		ifc->conv->inuse++; 
		unlock(ifc->conv); 
	} 
1998/0306    
	ifc->ifcid++; 
 
	wunlock(ifc); 
1998/0702/sys/src/9/ip/ipifc.c:161,1711998/0709/sys/src/9/ip/ipifc.c:165,180
1998/0306    
	wlock(ifc); 
 
1998/0307    
	/* dissociate routes */ 
1998/0630    
	ifc->conv->inuse--; 
1998/0709    
	if(ifc->m != nil && ifc->m->unbindonclose == 0){ 
		lock(ifc->conv); 
		ifc->conv->inuse--; 
		unlock(ifc->conv); 
	} 
1998/0307    
	ifc->ifcid++; 
1998/0306    
 
1998/0307    
	/* disassociate device */ 
1998/0630    
	(*ifc->m->unbind)(ifc); 
1998/0709    
	if(ifc->m != nil && ifc->m->unbind) 
		(*ifc->m->unbind)(ifc); 
1998/0307    
	memset(ifc->dev, 0, sizeof(ifc->dev)); 
	ifc->arg = nil; 
 
1998/0702/sys/src/9/ip/ipifc.c:199,2131998/0709/sys/src/9/ip/ipifc.c:208,221
1998/0306    
 
	ifc = (Ipifc*)c->ptcl; 
 
1998/0709    
	m = snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu); 
 
1998/0306    
	rlock(ifc); 
1998/0630    
	m = 0; 
	for(lifc = ifc->lifc; lifc; lifc = lifc->next) { 
		m += snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu); 
1998/0709    
	for(lifc = ifc->lifc; lifc; lifc = lifc->next) 
1998/0306    
		m += snprint(state+m, n - m, 
1998/0630    
			" %-20.20I %-20.20M %-20.20I %-7d %-7d %-7d %-7d\n", 
1998/0306    
				lifc->local, lifc->mask, lifc->remote, 
				ifc->in, ifc->out, ifc->inerr, ifc->outerr); 
1998/0630    
	} 
1998/0306    
	runlock(ifc); 
	return m; 
} 
1998/0709/sys/src/9/ip/ipifc.c:211,2171998/0717/sys/src/9/ip/ipifc.c:211,217 (short | long)
1998/0709    
	m = snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu); 
 
1998/0306    
	rlock(ifc); 
1998/0709    
	for(lifc = ifc->lifc; lifc; lifc = lifc->next) 
1998/0717    
	for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next) 
1998/0306    
		m += snprint(state+m, n - m, 
1998/0630    
			" %-20.20I %-20.20M %-20.20I %-7d %-7d %-7d %-7d\n", 
1998/0306    
				lifc->local, lifc->mask, lifc->remote, 
1998/0709/sys/src/9/ip/ipifc.c:374,3831998/0717/sys/src/9/ip/ipifc.c:374,379
1998/0306    
		break; 
	} 
 
	if(waserror()){ 
		wunlock(ifc); 
		panic("ipifcadd"); 
	} 
	wlock(ifc); 
 
	/* ignore if this is already a local address for this ifc */ 
1998/0709/sys/src/9/ip/ipifc.c:433,4391998/0717/sys/src/9/ip/ipifc.c:429,434
1998/0306    
 
out: 
	wunlock(ifc); 
	poperror(); 
	return nil; 
} 
 
1998/0709/sys/src/9/ip/ipifc.c:457,4691998/0717/sys/src/9/ip/ipifc.c:452,459
1998/0306    
	parseip(ip, argv[1]); 
	parseipmask(mask, argv[2]); 
 
	if(dolock){ 
		if(waserror()){ 
			wunlock(ifc); 
			nexterror(); 
		} 
1998/0717    
	if(dolock) 
1998/0306    
		wlock(ifc); 
	} 
 
	/* find address on this interface and remove from chain */ 
	lifc = nil; 
1998/0709/sys/src/9/ip/ipifc.c:475,4821998/0717/sys/src/9/ip/ipifc.c:465,475
1998/0306    
			break; 
		} 
 
	if(lifc == nil) 
1998/0717    
	if(lifc == nil){ 
		if(dolock) 
			wunlock(ifc); 
1998/0306    
		return "address not on this interface"; 
1998/0717    
	} 
1998/0306    
 
	/* disassociate any addresses */ 
	while(lifc->link) 
1998/0709/sys/src/9/ip/ipifc.c:491,5001998/0717/sys/src/9/ip/ipifc.c:484,491
1998/0306    
	free(lifc); 
 
out: 
	if(dolock){ 
1998/0717    
	if(dolock) 
1998/0306    
		wunlock(ifc); 
		poperror(); 
	} 
	return nil; 
} 
 
1998/0717/sys/src/9/ip/ipifc.c:1096,11011998/0728/sys/src/9/ip/ipifc.c:1096,1116 (short | long)
1998/0306    
	} 
	return 0; 
} 
1998/0728    
int 
ipisbm(uchar *ip) 
{ 
	if(isv4(ip)){ 
		if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0) 
			return V4; 
		if(ipcmp(ip, IPv4bcast) == 0) 
			return V4; 
	} else { 
		if(ip[0] == 0xff) 
			return V6; 
	} 
	return 0; 
} 
 
1998/0306    
 
/* 
 *  add a multicast address to an interface, called with c->car locked 
1998/0728/sys/src/9/ip/ipifc.c:213,2191998/0825/sys/src/9/ip/ipifc.c:213,219 (short | long)
Bug fix: print format.
rsc Fri Mar 4 12:44:25 2005
1998/0306    
	rlock(ifc); 
1998/0717    
	for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next) 
1998/0306    
		m += snprint(state+m, n - m, 
1998/0630    
			" %-20.20I %-20.20M %-20.20I %-7d %-7d %-7d %-7d\n", 
1998/0825    
			" %-20.20I %-20.20M %-20.20I %-7lud %-7lud %-7lud %-7lud\n", 
1998/0306    
				lifc->local, lifc->mask, lifc->remote, 
				ifc->in, ifc->out, ifc->inerr, ifc->outerr); 
	runlock(ifc); 
1998/0825/sys/src/9/ip/ipifc.c:483,4891998/0930/sys/src/9/ip/ipifc.c:483,488 (short | long)
1998/0306    
 
	free(lifc); 
 
out: 
1998/0717    
	if(dolock) 
1998/0306    
		wunlock(ifc); 
	return nil; 
1998/0930/sys/src/9/ip/ipifc.c:216,2211998/1005/sys/src/9/ip/ipifc.c:216,223 (short | long)
1998/0825    
			" %-20.20I %-20.20M %-20.20I %-7lud %-7lud %-7lud %-7lud\n", 
1998/0306    
				lifc->local, lifc->mask, lifc->remote, 
				ifc->in, ifc->out, ifc->inerr, ifc->outerr); 
1998/1005    
	if(ifc->lifc == nil) 
		m += snprint(state+m, n - m, "\n"); 
1998/0306    
	runlock(ifc); 
	return m; 
} 
1998/0930/sys/src/9/ip/ipifc.c:394,4011998/1005/sys/src/9/ip/ipifc.c:396,407
1998/0306    
 
	/* add a route for the local network */ 
	type = Rifc; 
	if(ipcmp(mask, IPallbits) == 0) 
1998/1005    
	if(ipcmp(mask, IPallbits) == 0){ 
		/* point to point networks are a hack */ 
		if(ipcmp(ip, rem) == 0) 
			findprimaryip(f, lifc->local); 
1998/0306    
		type |= Rptpt; 
1998/1005    
	} 
1998/0306    
	if(isv4(ip)) 
1998/0313    
		v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, ip+IPv4off, type); 
1998/0306    
	else 
1998/0930/sys/src/9/ip/ipifc.c:403,4081998/1005/sys/src/9/ip/ipifc.c:409,417
1998/0306    
 
1998/0313    
	addselfcache(f, ifc, lifc, ip, Runi); 
1998/0306    
 
1998/1005    
	if(type & Rptpt) 
		goto out; 
 
1998/0306    
	/* add subnet directed broadcast addresses to the self cache */ 
	for(i = 0; i < IPaddrlen; i++) 
		bcast[i] = (ip[i] & mask[i]) | ~mask[i]; 
1998/0930/sys/src/9/ip/ipifc.c:948,9531998/1005/sys/src/9/ip/ipifc.c:957,985
1998/0306    
} 
 
/* 
1998/1005    
 *  returns first ip address configured 
 */ 
void 
findprimaryip(Fs *f, uchar *local) 
{ 
	Conv **cp, **e; 
	Ipifc *ifc; 
	Iplifc *lifc; 
 
	/* find first ifc local address */ 
	e = &f->ipifc->conv[f->ipifc->nc]; 
	for(cp = f->ipifc->conv; cp < e; cp++){ 
		if(*cp == 0) 
			continue; 
		ifc = (Ipifc*)(*cp)->ptcl; 
		for(lifc = ifc->lifc; lifc; lifc = lifc->next){ 
			ipmove(local, lifc->local); 
			return; 
		} 
	} 
} 
 
/* 
1998/0306    
 *  find the local address 'closest' to the remote system, copy it to 
 *  local and return the ifc for that address 
 */ 
1998/0930/sys/src/9/ip/ipifc.c:956,9621998/1005/sys/src/9/ip/ipifc.c:988,993
1998/0306    
{ 
	Ipifc *ifc; 
	Iplifc *lifc; 
1998/0313    
	Conv **cp, **e; 
1998/0306    
	Route *r; 
	uchar gate[IPaddrlen]; 
	uchar gnet[IPaddrlen]; 
1998/0930/sys/src/9/ip/ipifc.c:971,9811998/1005/sys/src/9/ip/ipifc.c:1002,1007
1998/0306    
		else 
			ipmove(gate, r->v6.gate); 
 
		if(r->type & Rifc){ 
			ipmove(local, gate); 
			goto out; 
		} 
                 
		/* find ifc address closest to the gateway to use */ 
		for(lifc = ifc->lifc; lifc; lifc = lifc->next){ 
			maskip(gate, lifc->mask, gnet); 
1998/0930/sys/src/9/ip/ipifc.c:985,10021998/1005/sys/src/9/ip/ipifc.c:1011,1018
1998/0306    
			} 
		} 
	} 
		                 
	/* no match, choose first ifc local address */ 
1998/0313    
	e = &f->ipifc->conv[f->ipifc->nc]; 
	for(cp = f->ipifc->conv; cp < e; cp++){ 
1998/0306    
		if(*cp == 0) 
			continue; 
		ifc = (Ipifc*)(*cp)->ptcl; 
		for(lifc = ifc->lifc; lifc; lifc = lifc->next){ 
			ipmove(local, lifc->local); 
			goto out; 
		} 
	} 
1998/1005    
 
	findprimaryip(f, local); 
1998/0306    
 
out: 
1998/0313    
	qunlock(f->ipifc); 
1998/1005/sys/src/9/ip/ipifc.c:208,2141999/0223/sys/src/9/ip/ipifc.c:208,214 (short | long)
1998/0306    
 
	ifc = (Ipifc*)c->ptcl; 
 
1998/0709    
	m = snprint(state, n, "%-12.12s %-5d", ifc->dev, ifc->maxmtu); 
1999/0223    
	m = snprint(state, n, "%-12s %-5d", ifc->dev, ifc->maxmtu); 
1998/0709    
 
1998/0306    
	rlock(ifc); 
1998/0717    
	for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next) 
1999/0223/sys/src/9/ip/ipifc.c:136,1441999/0302/sys/src/9/ip/ipifc.c:136,144 (short | long)
1998/0306    
	ifc->minmtu = ifc->m->minmtu; 
	ifc->maxmtu = ifc->m->maxmtu; 
1998/0709    
	if(ifc->m->unbindonclose == 0){ 
		lock(ifc->conv); 
1999/0302    
		qlock(ifc->conv); 
1998/0709    
		ifc->conv->inuse++; 
		unlock(ifc->conv); 
1999/0302    
		qunlock(ifc->conv); 
1998/0709    
	} 
1998/0306    
	ifc->ifcid++; 
 
1999/0223/sys/src/9/ip/ipifc.c:166,1741999/0302/sys/src/9/ip/ipifc.c:166,174
1998/0306    
 
1998/0307    
	/* dissociate routes */ 
1998/0709    
	if(ifc->m != nil && ifc->m->unbindonclose == 0){ 
		lock(ifc->conv); 
1999/0302    
		qlock(ifc->conv); 
1998/0709    
		ifc->conv->inuse--; 
		unlock(ifc->conv); 
1999/0302    
		qunlock(ifc->conv); 
1998/0709    
	} 
1998/0307    
	ifc->ifcid++; 
1998/0306    
 
1999/0223/sys/src/9/ip/ipifc.c:305,3111999/0302/sys/src/9/ip/ipifc.c:305,311
1998/0307    
	m = ifc->m; 
1998/0516    
	if(m != nil && m->unbindonclose) 
1998/0307    
		ipifcunbind(ifc); 
1998/0306    
	unlock(c); 
1999/0302    
	qunlock(c); 
1998/0306    
} 
 
/* 
1999/0302/sys/src/9/ip/ipifc.c:66,711999/0731/sys/src/9/ip/ipifc.c:66,72 (short | long)
1998/0313    
static void	remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a); 
1998/0306    
static char*	ipifcjoinmulti(Ipifc *ifc, char **argv, int argc); 
static char*	ipifcleavemulti(Ipifc *ifc, char **argv, int argc); 
1999/0731    
static void	ipifcregisterproxy(Fs*, Ipifc*, uchar*); 
1998/0423    
 
/* 
 *  link in a new medium 
1999/0302/sys/src/9/ip/ipifc.c:409,4161999/0731/sys/src/9/ip/ipifc.c:410,419
1998/0306    
 
1998/0313    
	addselfcache(f, ifc, lifc, ip, Runi); 
1998/0306    
 
1998/1005    
	if(type & Rptpt) 
1999/0731    
	if(type & Rptpt){ 
		ipifcregisterproxy(f, ifc, rem); 
1998/1005    
		goto out; 
1999/0731    
	} 
1998/1005    
 
1998/0306    
	/* add subnet directed broadcast addresses to the self cache */ 
	for(i = 0; i < IPaddrlen; i++) 
1999/0302/sys/src/9/ip/ipifc.c:436,4411999/0731/sys/src/9/ip/ipifc.c:439,448
1998/0306    
 
1998/0313    
	addselfcache(f, ifc, lifc, IPv4bcast, Rbcast); 
1998/0306    
 
1999/0731    
	/* register the address on this network for address resolution */ 
	if(ifc->m->areg != nil) 
		(*ifc->m->areg)(ifc, ip); 
 
1998/0306    
out: 
	wunlock(ifc); 
	return nil; 
1999/0302/sys/src/9/ip/ipifc.c:1231,12331999/0731/sys/src/9/ip/ipifc.c:1238,1267
1998/0306    
	return nil; 
} 
 
1999/0731    
static void 
ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip) 
{ 
	Conv **cp, **e; 
	Ipifc *nifc; 
	Iplifc *lifc; 
	uchar net[IPaddrlen]; 
 
	/* register the address on any network that will proxy for us */ 
	e = &f->ipifc->conv[f->ipifc->nc]; 
	for(cp = f->ipifc->conv; cp < e; cp++){ 
		if(*cp == nil) 
			continue; 
		nifc = (Ipifc*)(*cp)->ptcl; 
		if(nifc->m->areg == nil) 
			continue; 
		if(nifc == ifc) 
			continue; 
		for(lifc = nifc->lifc; lifc; lifc = lifc->next){ 
			maskip(ip, lifc->mask, net); 
			if(ipcmp(net, lifc->remote) == 0){ 
				(*nifc->m->areg)(nifc, ip); 
				break; 
			} 
		} 
	} 
} 
1999/0731/sys/src/9/ip/ipifc.c:1244,12491999/0803/sys/src/9/ip/ipifc.c:1244,1250 (short | long)
1999/0731    
	Conv **cp, **e; 
	Ipifc *nifc; 
	Iplifc *lifc; 
1999/0803    
	Medium *m; 
1999/0731    
	uchar net[IPaddrlen]; 
 
	/* register the address on any network that will proxy for us */ 
1999/0731/sys/src/9/ip/ipifc.c:1252,12671999/0803/sys/src/9/ip/ipifc.c:1253,1274
1999/0731    
		if(*cp == nil) 
			continue; 
		nifc = (Ipifc*)(*cp)->ptcl; 
		if(nifc->m->areg == nil) 
			continue; 
		if(nifc == ifc) 
			continue; 
1999/0803    
 
		rlock(nifc); 
		m = nifc->m; 
		if(m == nil || m->areg == nil){ 
			runlock(nifc); 
			continue; 
		} 
1999/0731    
		for(lifc = nifc->lifc; lifc; lifc = lifc->next){ 
			maskip(ip, lifc->mask, net); 
			if(ipcmp(net, lifc->remote) == 0){ 
				(*nifc->m->areg)(nifc, ip); 
1999/0803    
				(*m->areg)(nifc, ip); 
1999/0731    
				break; 
			} 
		} 
1999/0803    
		runlock(nifc); 
1999/0731    
	} 
} 
1999/0803/sys/src/9/ip/ipifc.c:345,3541999/0909/sys/src/9/ip/ipifc.c:345,359 (short | long)
1998/0702    
 
1998/0313    
	f = ifc->conv->p->f; 
 
1999/0909    
	type = Rifc; 
1998/0306    
	memset(ip, 0, IPaddrlen); 
	memset(mask, 0, IPaddrlen); 
	memset(rem, 0, IPaddrlen); 
	switch(argc){ 
1999/0909    
	case 6: 
		if(strcmp(argv[5], "proxy") == 0) 
			type |= Rproxy; 
		/* fall through */ 
1998/0306    
	case 5: 
		mtu = strtoul(argv[4], 0, 0); 
		if(mtu >= ifc->m->minmtu && mtu <= ifc->m->maxmtu) 
1999/0803/sys/src/9/ip/ipifc.c:396,4021999/0909/sys/src/9/ip/ipifc.c:401,406
1998/0306    
	*l = lifc; 
 
	/* add a route for the local network */ 
	type = Rifc; 
1998/1005    
	if(ipcmp(mask, IPallbits) == 0){ 
		/* point to point networks are a hack */ 
		if(ipcmp(ip, rem) == 0) 
1999/0803/sys/src/9/ip/ipifc.c:410,4161999/0909/sys/src/9/ip/ipifc.c:414,420
1998/0306    
 
1998/0313    
	addselfcache(f, ifc, lifc, ip, Runi); 
1998/0306    
 
1999/0731    
	if(type & Rptpt){ 
1999/0909    
	if((type & (Rptpt|Rproxy)) == (Rptpt|Rproxy)){ 
1999/0731    
		ipifcregisterproxy(f, ifc, rem); 
1998/1005    
		goto out; 
1999/0731    
	} 
1999/0803/sys/src/9/ip/ipifc.c:1088,10961999/0909/sys/src/9/ip/ipifc.c:1092,1098
1998/0313    
	r = v6lookup(f, ip); 
1998/0306    
	if(r == nil) 
		return 0; 
	if((r->type & Rifc) == 0) 
		return 0; 
	if((r->type & Rptpt) == 0) 
1999/0909    
	if((r->type & (Rifc|Rptpt|Rproxy)) != (Rifc|Rptpt|Rproxy)) 
1998/0306    
		return 0; 
 
	/* see if this is on the right interface */ 
1999/0909/sys/src/9/ip/ipifc.c:475,4891999/1029/sys/src/9/ip/ipifc.c:475,501 (short | long)
1998/0717    
	if(dolock) 
1998/0306    
		wlock(ifc); 
 
	/* find address on this interface and remove from chain */ 
	lifc = nil; 
	for(l = &ifc->lifc; *l; l = &(*l)->next) 
		if(memcmp(ip, (*l)->local, IPaddrlen) == 0) 
		if(memcmp(mask, (*l)->mask, IPaddrlen) == 0){ 
			lifc = *l; 
1999/1029    
	/* Are we point to point */ 
	type = 0; 
	if(ipcmp(mask, IPallbits) == 0) 
		type = Rptpt; 
 
	/* 
	 *  find address on this interface and remove from chain. 
	 *  for pt to pt we actually specify the remote address at the 
	 *  addresss to remove. 
	 */ 
	l = &ifc->lifc; 
	for(lifc = *l; lifc != nil; lifc = lifc->next) { 
		addr = lifc->local; 
		if(type == Rptpt) 
			addr = lifc->remote; 
		if(memcmp(ip, addr, IPaddrlen) == 0 && memcmp(mask, lifc->mask, IPaddrlen) == 0) { 
1998/0306    
			*l = lifc->next; 
			break; 
		} 
1999/1029    
		l = &lifc->next; 
	} 
1998/0306    
 
1998/0717    
	if(lifc == nil){ 
		if(dolock) 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)