xref: /inferno-os/os/ip/ip.h (revision e1bd49a1e1823eab71c293efd1bd0c9b83c350c9)
1 typedef struct	Conv	Conv;
2 typedef struct	Fs	Fs;
3 typedef union	Hwaddr	Hwaddr;
4 typedef struct	IP	IP;
5 typedef struct	IPaux	IPaux;
6 typedef struct	Ipself	Ipself;
7 typedef struct	Ipselftab	Ipselftab;
8 typedef struct	Iplink	Iplink;
9 typedef struct	Iplifc	Iplifc;
10 typedef struct	Ipmulti	Ipmulti;
11 typedef struct	IProuter IProuter;
12 typedef struct	Ipifc	Ipifc;
13 typedef struct	Iphash	Iphash;
14 typedef struct	Ipht	Ipht;
15 typedef struct	Netlog	Netlog;
16 typedef struct	Ifclog	Ifclog;
17 typedef struct	Medium	Medium;
18 typedef struct	Proto	Proto;
19 typedef struct	Arpent	Arpent;
20 typedef struct	Arp Arp;
21 typedef struct	Route	Route;
22 
23 typedef struct	Routerparams	Routerparams;
24 typedef struct 	Hostparams	Hostparams;
25 typedef struct 	V6router	V6router;
26 typedef struct	V6params	V6params;
27 
28 #pragma incomplete Arp
29 #pragma	incomplete Ifclog
30 #pragma incomplete Ipself
31 #pragma incomplete Ipselftab
32 #pragma incomplete IP
33 #pragma incomplete Netlog
34 
35 enum
36 {
37 	Addrlen=	64,
38 	Maxproto=	20,
39 	Nhash=		64,
40 	Maxincall=	5,
41 	Nchans=		256,
42 	MAClen=		16,		/* longest mac address */
43 
44 	MAXTTL=		255,
45 	DFLTTOS=	0,
46 
47 	IPaddrlen=	16,
48 	IPv4addrlen=	4,
49 	IPv4off=	12,
50 	IPllen=		4,
51 
52 	/* ip versions */
53 	V4=		4,
54 	V6=		6,
55 	IP_VER4= 	0x40,
56 	IP_VER6=	0x60,
57 
58 	/* 2^Lroot trees in the root table */
59 	Lroot=		10,
60 
61 	Maxpath =	64,
62 };
63 
64 enum
65 {
66 	Idle=		0,
67 	Announcing=	1,
68 	Announced=	2,
69 	Connecting=	3,
70 	Connected=	4,
71 };
72 
73 /*
74  *  one per conversation directory
75  */
76 struct Conv
77 {
78 	QLock;
79 
80 	int	x;			/* conversation index */
81 	Proto*	p;
82 
83 	int	restricted;		/* remote port is restricted */
84 	uint	ttl;			/* max time to live */
85 	uint	tos;			/* type of service */
86 	int	ignoreadvice;		/* don't terminate connection on icmp errors */
87 
88 	uchar	ipversion;
89 	uchar	laddr[IPaddrlen];	/* local IP address */
90 	uchar	raddr[IPaddrlen];	/* remote IP address */
91 	ushort	lport;			/* local port number */
92 	ushort	rport;			/* remote port number */
93 
94 	char	*owner;			/* protections */
95 	int	perm;
96 	int	inuse;			/* opens of listen/data/ctl */
97 	int	length;
98 	int	state;
99 
100 	/* udp specific */
101 	int	headers;		/* data src/dst headers in udp */
102 	int	reliable;		/* true if reliable udp */
103 
104 	Conv*	incall;			/* calls waiting to be listened for */
105 	Conv*	next;
106 
107 	Queue*	rq;			/* queued data waiting to be read */
108 	Queue*	wq;			/* queued data waiting to be written */
109 	Queue*	eq;			/* returned error packets */
110 	Queue*	sq;			/* snooping queue */
111 	Ref	snoopers;		/* number of processes with snoop open */
112 
113 	Rendez	cr;
114 	char	cerr[ERRMAX];
115 
116 	QLock	listenq;
117 	Rendez	listenr;
118 
119 	Ipmulti	*multi;			/* multicast bindings for this interface */
120 
121 	void*	ptcl;			/* protocol specific stuff */
122 
123 	Route	*r;			/* last route used */
124 	ulong	rgen;			/* routetable generation for *r */
125 };
126 
127 struct Medium
128 {
129 	char	*name;
130 	int	hsize;		/* medium header size */
131 	int	mintu;		/* default min mtu */
132 	int	maxtu;		/* default max mtu */
133 	int	maclen;		/* mac address length  */
134 	void	(*bind)(Ipifc*, int, char**);
135 	void	(*unbind)(Ipifc*);
136 	void	(*bwrite)(Ipifc *ifc, Block *b, int version, uchar *ip);
137 
138 	/* for arming interfaces to receive multicast */
139 	void	(*addmulti)(Ipifc *ifc, uchar *a, uchar *ia);
140 	void	(*remmulti)(Ipifc *ifc, uchar *a, uchar *ia);
141 
142 	/* process packets written to 'data' */
143 	void	(*pktin)(Fs *f, Ipifc *ifc, Block *bp);
144 
145 	/* routes for router boards */
146 	void	(*addroute)(Ipifc *ifc, int, uchar*, uchar*, uchar*, int);
147 	void	(*remroute)(Ipifc *ifc, int, uchar*, uchar*);
148 	void	(*flushroutes)(Ipifc *ifc);
149 
150 	/* for routing multicast groups */
151 	void	(*joinmulti)(Ipifc *ifc, uchar *a, uchar *ia);
152 	void	(*leavemulti)(Ipifc *ifc, uchar *a, uchar *ia);
153 
154 	/* address resolution */
155 	void	(*ares)(Fs*, int, uchar*, uchar*, int, int);	/* resolve */
156 	void	(*areg)(Ipifc*, uchar*);			/* register */
157 
158 	/* v6 address generation */
159 	void	(*pref2addr)(uchar *pref, uchar *ea);
160 
161 	int	unbindonclose;	/* if non-zero, unbind on last close */
162 };
163 
164 /* logical interface associated with a physical one */
165 struct Iplifc
166 {
167 	uchar	local[IPaddrlen];
168 	uchar	mask[IPaddrlen];
169 	uchar	remote[IPaddrlen];
170 	uchar	net[IPaddrlen];
171 	uchar	tentative;	/* =1 => v6 dup disc on, =0 => confirmed unique */
172 	uchar	onlink;		/* =1 => onlink, =0 offlink. */
173 	uchar	autoflag;	/* v6 autonomous flag */
174 	long 	validlt;	/* v6 valid lifetime */
175 	long 	preflt;		/* v6 preferred lifetime */
176 	long	origint;	/* time when addr was added */
177 	Iplink	*link;		/* addresses linked to this lifc */
178 	Iplifc	*next;
179 };
180 
181 /* binding twixt Ipself and Iplifc */
182 struct Iplink
183 {
184 	Ipself	*self;
185 	Iplifc	*lifc;
186 	Iplink	*selflink;	/* next link for this local address */
187 	Iplink	*lifclink;	/* next link for this ifc */
188 	ulong	expire;
189 	Iplink	*next;		/* free list */
190 	int	ref;
191 };
192 
193 /* rfc 2461, pp.40--43. */
194 
195 /* default values, one per stack */
196 struct Routerparams {
197 	int	mflag;
198 	int	oflag;
199 	int 	maxraint;
200 	int	minraint;
201 	int	linkmtu;
202 	int	reachtime;
203 	int	rxmitra;
204 	int	ttl;
205 	int	routerlt;
206 };
207 
208 struct Hostparams {
209 	int	rxmithost;
210 };
211 
212 struct Ipifc
213 {
214 	RWlock;
215 
216 	Conv	*conv;		/* link to its conversation structure */
217 	char	dev[64];	/* device we're attached to */
218 	Medium	*m;		/* Media pointer */
219 	int	maxtu;		/* Maximum transfer unit */
220 	int	mintu;		/* Minumum tranfer unit */
221 	int	mbps;		/* megabits per second */
222 	void	*arg;		/* medium specific */
223 	int	reassemble;	/* reassemble IP packets before forwarding */
224 
225 	/* these are used so that we can unbind on the fly */
226 	Lock	idlock;
227 	uchar	ifcid;		/* incremented each 'bind/unbind/add/remove' */
228 	int	ref;		/* number of proc's using this ipifc */
229 	Rendez	wait;		/* where unbinder waits for ref == 0 */
230 	int	unbinding;
231 
232 	uchar	mac[MAClen];	/* MAC address */
233 
234 	Iplifc	*lifc;		/* logical interfaces on this physical one */
235 
236 	ulong	in, out;	/* message statistics */
237 	ulong	inerr, outerr;	/* ... */
238 
239 	uchar	sendra6;	/* == 1 => send router advs on this ifc	*/
240 	uchar	recvra6;	/* == 1 => recv router advs on this ifc */
241 	Routerparams rp;	/* router parameters as in RFC 2461, pp.40--43.
242 					used only if node is router */
243 };
244 
245 /*
246  *  one per multicast-lifc pair used by a Conv
247  */
248 struct Ipmulti
249 {
250 	uchar	ma[IPaddrlen];
251 	uchar	ia[IPaddrlen];
252 	Ipmulti	*next;
253 };
254 
255 /*
256  *  hash table for 2 ip addresses + 2 ports
257  */
258 enum
259 {
260 	Nipht=		521,	/* convenient prime */
261 
262 	IPmatchexact=	0,	/* match on 4 tuple */
263 	IPmatchany,		/* *!* */
264 	IPmatchport,		/* *!port */
265 	IPmatchaddr,		/* addr!* */
266 	IPmatchpa,		/* addr!port */
267 };
268 struct Iphash
269 {
270 	Iphash	*next;
271 	Conv	*c;
272 	int	match;
273 };
274 struct Ipht
275 {
276 	Lock;
277 	Iphash	*tab[Nipht];
278 };
279 void iphtadd(Ipht*, Conv*);
280 void iphtrem(Ipht*, Conv*);
281 Conv* iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp);
282 
283 /*
284  *  one per multiplexed protocol
285  */
286 struct Proto
287 {
288 	QLock;
289 	char*		name;		/* protocol name */
290 	int		x;		/* protocol index */
291 	int		ipproto;	/* ip protocol type */
292 
293 	char*		(*connect)(Conv*, char**, int);
294 	char*		(*announce)(Conv*, char**, int);
295 	char*		(*bind)(Conv*, char**, int);
296 	int		(*state)(Conv*, char*, int);
297 	void		(*create)(Conv*);
298 	void		(*close)(Conv*);
299 	void		(*rcv)(Proto*, Ipifc*, Block*);
300 	char*		(*ctl)(Conv*, char**, int);
301 	void		(*advise)(Proto*, Block*, char*);
302 	int		(*stats)(Proto*, char*, int);
303 	int		(*local)(Conv*, char*, int);
304 	int		(*remote)(Conv*, char*, int);
305 	int		(*inuse)(Conv*);
306 	int		(*gc)(Proto*);	/* returns true if any conversations are freed */
307 
308 	Fs		*f;		/* file system this proto is part of */
309 	Conv		**conv;		/* array of conversations */
310 	int		ptclsize;	/* size of per protocol ctl block */
311 	int		nc;		/* number of conversations */
312 	int		ac;
313 	Qid		qid;		/* qid for protocol directory */
314 	ushort		nextport;
315 	ushort		nextrport;
316 
317 	void		*priv;
318 };
319 
320 /*
321  *  Stream for sending packets to user level
322  */
323 struct IProuter {
324 	QLock;
325 	int	opens;
326 	Queue	*q;
327 };
328 
329 /*
330  *  one per IP protocol stack
331  */
332 struct Fs
333 {
334 	RWlock;
335 	int	dev;
336 
337 	int	np;
338 	Proto*	p[Maxproto+1];		/* list of supported protocols */
339 	Proto*	t2p[256];		/* vector of all protocols */
340 	Proto*	ipifc;			/* kludge for ipifcremroute & ipifcaddroute */
341 	Proto*	ipmux;			/* kludge for finding an ip multiplexor */
342 
343 	IP	*ip;
344 	Ipselftab	*self;
345 	Arp	*arp;
346 	V6params	*v6p;
347 	IProuter iprouter;
348 
349 	Route	*v4root[1<<Lroot];	/* v4 routing forest */
350 	Route	*v6root[1<<Lroot];	/* v6 routing forest */
351 	Route	*queue;			/* used as temp when reinjecting routes */
352 
353 	Netlog	*alog;
354 	Ifclog	*ilog;
355 
356 	char	ndb[1024];		/* an ndb entry for this interface */
357 	int	ndbvers;
358 	long	ndbmtime;
359 };
360 
361 /* one per default router known to host */
362 struct V6router {
363 	uchar	inuse;
364 	Ipifc	*ifc;
365 	int	ifcid;
366 	uchar	routeraddr[IPaddrlen];
367 	long	ltorigin;
368 	Routerparams	rp;
369 };
370 
371 struct V6params
372 {
373 	Routerparams	rp;		/* v6 params, one copy per node now */
374 	Hostparams	hp;
375 	V6router	v6rlist[3];	/* max 3 default routers, currently */
376 	int		cdrouter;	/* uses only v6rlist[cdrouter] if   */
377 					/* cdrouter >= 0. */
378 };
379 
380 
381 int	Fsconnected(Conv*, char*);
382 Conv*	Fsnewcall(Conv*, uchar*, ushort, uchar*, ushort, uchar);
383 int	Fspcolstats(char*, int);
384 int	Fsproto(Fs*, Proto*);
385 int	Fsbuiltinproto(Fs*, uchar);
386 Conv*	Fsprotoclone(Proto*, char*);
387 Proto*	Fsrcvpcol(Fs*, uchar);
388 Proto*	Fsrcvpcolx(Fs*, uchar);
389 char*	Fsstdconnect(Conv*, char**, int);
390 char*	Fsstdannounce(Conv*, char**, int);
391 char*	Fsstdbind(Conv*, char**, int);
392 ulong	scalednconv(void);
393 
394 /*
395  *  logging
396  */
397 enum
398 {
399 	Logip=		1<<1,
400 	Logtcp=		1<<2,
401 	Logfs=		1<<3,
402 	Logil=		1<<4,
403 	Logicmp=	1<<5,
404 	Logudp=		1<<6,
405 	Logcompress=	1<<7,
406 	Logilmsg=	1<<8,
407 	Loggre=		1<<9,
408 	Logppp=		1<<10,
409 	Logtcprxmt=	1<<11,
410 	Logigmp=	1<<12,
411 	Logudpmsg=	1<<13,
412 	Logipmsg=	1<<14,
413 	Logrudp=	1<<15,
414 	Logrudpmsg=	1<<16,
415 	Logesp=		1<<17,
416 	Logtcpwin=	1<<18,
417 };
418 
419 void	netloginit(Fs*);
420 void	netlogopen(Fs*);
421 void	netlogclose(Fs*);
422 void	netlogctl(Fs*, char*, int);
423 long	netlogread(Fs*, void*, ulong, long);
424 void	netlog(Fs*, int, char*, ...);
425 void	ifcloginit(Fs*);
426 long	ifclogread(Fs*, Chan *,void*, ulong, long);
427 void	ifclog(Fs*, uchar *, int);
428 void	ifclogopen(Fs*, Chan*);
429 void	ifclogclose(Fs*, Chan*);
430 
431 /*
432  *  iproute.c
433  */
434 typedef	struct RouteTree RouteTree;
435 typedef struct Routewalk Routewalk;
436 typedef struct V4route V4route;
437 typedef struct V6route V6route;
438 
439 enum
440 {
441 
442 	/* type bits */
443 	Rv4=		(1<<0),		/* this is a version 4 route */
444 	Rifc=		(1<<1),		/* this route is a directly connected interface */
445 	Rptpt=		(1<<2),		/* this route is a pt to pt interface */
446 	Runi=		(1<<3),		/* a unicast self address */
447 	Rbcast=		(1<<4),		/* a broadcast self address */
448 	Rmulti=		(1<<5),		/* a multicast self address */
449 	Rproxy=		(1<<6),		/* this route should be proxied */
450 };
451 
452 struct Routewalk
453 {
454 	int	o;
455 	int	h;
456 	char*	p;
457 	char*	e;
458 	void*	state;
459 	void	(*walk)(Route*, Routewalk*);
460 };
461 
462 struct	RouteTree
463 {
464 	Route*	right;
465 	Route*	left;
466 	Route*	mid;
467 	uchar	depth;
468 	uchar	type;
469 	uchar	ifcid;		/* must match ifc->id */
470 	Ipifc	*ifc;
471 	char	tag[4];
472 	int	ref;
473 };
474 
475 struct V4route
476 {
477 	ulong	address;
478 	ulong	endaddress;
479 	uchar	gate[IPv4addrlen];
480 };
481 
482 struct V6route
483 {
484 	ulong	address[IPllen];
485 	ulong	endaddress[IPllen];
486 	uchar	gate[IPaddrlen];
487 };
488 
489 struct Route
490 {
491 	RouteTree;
492 
493 	union {
494 		V6route	v6;
495 		V4route v4;
496 	};
497 };
498 extern void	v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type);
499 extern void	v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type);
500 extern void	v4delroute(Fs *f, uchar *a, uchar *mask, int dolock);
501 extern void	v6delroute(Fs *f, uchar *a, uchar *mask, int dolock);
502 extern Route*	v4lookup(Fs *f, uchar *a, Conv *c);
503 extern Route*	v6lookup(Fs *f, uchar *a, Conv *c);
504 extern long	routeread(Fs *f, char*, ulong, int);
505 extern long	routewrite(Fs *f, Chan*, char*, int);
506 extern void	routetype(int, char*);
507 extern void	ipwalkroutes(Fs*, Routewalk*);
508 extern void	convroute(Route*, uchar*, uchar*, uchar*, char*, int*);
509 
510 /*
511  *  devip.c
512  */
513 
514 /*
515  *  Hanging off every ip channel's ->aux is the following structure.
516  *  It maintains the state used by devip and iproute.
517  */
518 struct IPaux
519 {
520 	char	*owner;		/* the user that did the attach */
521 	char	tag[4];
522 };
523 
524 extern IPaux*	newipaux(char*, char*);
525 
526 /*
527  *  arp.c
528  */
529 struct Arpent
530 {
531 	uchar	ip[IPaddrlen];
532 	uchar	mac[MAClen];
533 	Medium	*type;			/* media type */
534 	Arpent*	hash;
535 	Block*	hold;
536 	Block*	last;
537 	uint	ctime;			/* time entry was created or refreshed */
538 	uint	utime;			/* time entry was last used */
539 	uchar	state;
540 	Arpent	*nextrxt;		/* re-transmit chain */
541 	uint	rtime;			/* time for next retransmission */
542 	uchar	rxtsrem;
543 	Ipifc	*ifc;
544 	uchar	ifcid;			/* must match ifc->id */
545 };
546 
547 extern void	arpinit(Fs*);
548 extern int	arpread(Arp*, char*, ulong, int);
549 extern int	arpwrite(Fs*, char*, int);
550 extern Arpent*	arpget(Arp*, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *h);
551 extern void	arprelease(Arp*, Arpent *a);
552 extern Block*	arpresolve(Arp*, Arpent *a, Medium *type, uchar *mac);
553 extern void	arpenter(Fs*, int version, uchar *ip, uchar *mac, int len, int norefresh);
554 
555 /*
556  * ipaux.c
557  */
558 
559 extern int	myetheraddr(uchar*, char*);
560 extern ulong	parseip(uchar*, char*);
561 extern ulong	parseipmask(uchar*, char*);
562 extern char*	v4parseip(uchar*, char*);
563 extern void	maskip(uchar *from, uchar *mask, uchar *to);
564 extern int	parsemac(uchar *to, char *from, int len);
565 extern uchar*	defmask(uchar*);
566 extern int	isv4(uchar*);
567 extern void	v4tov6(uchar *v6, uchar *v4);
568 extern int	v6tov4(uchar *v4, uchar *v6);
569 extern int	eipfmt(Fmt*);
570 
571 #define	ipmove(x, y) memmove(x, y, IPaddrlen)
572 #define	ipcmp(x, y) ( (x)[IPaddrlen-1] != (y)[IPaddrlen-1] || memcmp(x, y, IPaddrlen) )
573 
574 extern uchar IPv4bcast[IPaddrlen];
575 extern uchar IPv4bcastobs[IPaddrlen];
576 extern uchar IPv4allsys[IPaddrlen];
577 extern uchar IPv4allrouter[IPaddrlen];
578 extern uchar IPnoaddr[IPaddrlen];
579 extern uchar v4prefix[IPaddrlen];
580 extern uchar IPallbits[IPaddrlen];
581 
582 #define	NOW	TK2MS(MACHP(0)->ticks)
583 
584 /*
585  *  media
586  */
587 extern Medium	ethermedium;
588 extern Medium	nullmedium;
589 extern Medium	pktmedium;
590 extern Medium	tripmedium;
591 
592 /*
593  *  ipifc.c
594  */
595 extern Medium*	ipfindmedium(char *name);
596 extern void	addipmedium(Medium *med);
597 extern int	ipforme(Fs*, uchar *addr);
598 extern int	iptentative(Fs*, uchar *addr);
599 extern int	ipisbm(uchar *);
600 extern int	ipismulticast(uchar *);
601 extern Ipifc*	findipifc(Fs*, uchar *remote, int type);
602 extern void	findprimaryip(Fs*, uchar*);
603 extern void	findlocalip(Fs*, uchar *local, uchar *remote);
604 extern int	ipv4local(Ipifc *ifc, uchar *addr);
605 extern int	ipv6local(Ipifc *ifc, uchar *addr);
606 extern int	ipv6anylocal(Ipifc *ifc, uchar *addr);
607 extern Iplifc*	iplocalonifc(Ipifc *ifc, uchar *ip);
608 extern int	ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip);
609 extern int	ipismulticast(uchar *ip);
610 extern int	ipisbooting(void);
611 extern int	ipifccheckin(Ipifc *ifc, Medium *med);
612 extern void	ipifccheckout(Ipifc *ifc);
613 extern int	ipifcgrab(Ipifc *ifc);
614 extern void	ipifcaddroute(Fs*, int, uchar*, uchar*, uchar*, int);
615 extern void	ipifcremroute(Fs*, int, uchar*, uchar*);
616 extern void	ipifcremmulti(Conv *c, uchar *ma, uchar *ia);
617 extern void	ipifcaddmulti(Conv *c, uchar *ma, uchar *ia);
618 extern char*	ipifcrem(Ipifc *ifc, char **argv, int argc);
619 extern char*	ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp);
620 extern long	ipselftabread(Fs*, char *a, ulong offset, int n);
621 extern char*	ipifcaddpref6(Ipifc *ifc, char**argv, int argc);
622 extern void	ipsendra6(Fs *f, int on);
623 
624 /*
625  *  ip.c
626  */
627 extern void	iprouting(Fs*, int);
628 extern void	icmpnoconv(Fs*, Block*);
629 extern void	icmpcantfrag(Fs*, Block*, int);
630 extern void	icmpttlexceeded(Fs*, uchar*, Block*);
631 extern ushort	ipcsum(uchar*);
632 extern void	ipiput4(Fs*, Ipifc*, Block*);
633 extern void	ipiput6(Fs*, Ipifc*, Block*);
634 extern int	ipoput4(Fs*, Block*, int, int, int, Conv*);
635 extern int	ipoput6(Fs*, Block*, int, int, int, Conv*);
636 extern int	ipstats(Fs*, char*, int);
637 extern ushort	ptclbsum(uchar*, int);
638 extern ushort	ptclcsum(Block*, int, int);
639 extern void	ip_init(Fs*);
640 extern void	update_mtucache(uchar*, ulong);
641 extern ulong	restrict_mtu(uchar*, ulong);
642 
643 /*
644  * bootp.c
645  */
646 char*	(*bootp)(Ipifc*);
647 int	(*bootpread)(char*, ulong, int);
648 
649 /*
650  *  iprouter.c
651  */
652 void	useriprouter(Fs*, Ipifc*, Block*);
653 void	iprouteropen(Fs*);
654 void	iprouterclose(Fs*);
655 long	iprouterread(Fs*, void*, int);
656 
657 /*
658  *  resolving inferno/plan9 differences
659  */
660 Chan*		commonfdtochan(int, int, int, int);
661 char*		commonuser(void);
662 char*		commonerror(void);
663 
664 /*
665  * chandial.c
666  */
667 extern Chan*	chandial(char*, char*, char*, Chan**);
668 
669 /*
670  *  global to all of the stack
671  */
672 extern void	(*igmpreportfn)(Ipifc*, uchar*);
673