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