inet.c
来自「操作系统SunOS 4.1.3版本的源码」· C语言 代码 · 共 590 行
C
590 行
/* * inet.c * * @(#)inet.c 1.1 * Copyright (c) 1986 by Sun Microsystems, Inc. *//* * Standalone IP send and receive - specific to Ethernet * Includes ARP and Reverse ARP */#include <stand/saio.h>#include <sys/socket.h>#include <net/if.h>#include <net/if_arp.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include <netinet/in_systm.h>#include <netinet/ip.h>#include <stand/sainet.h>#include <mon/sunromvec.h>#include <mon/idprom.h>#define INADDR1_ANY 0x000000ff#ifdef OPENPROMS#define millitime() prom_gettime()#else#define millitime() (*romp->v_nmiclock)#endif !OPENPROMSstruct ether_addr etherbroadcastaddr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,};struct in_addr my_in_addr;struct in_addr null_in_addr;struct arp_packet { struct ether_header arp_eh; struct ether_arp arp_ea;#define used_size (sizeof (struct ether_header)+sizeof (struct ether_arp)) char filler[ETHERMIN - sizeof (struct ether_arp)];};#define WAITCNT 2 /* 4 seconds before bitching about arp/revarp */extern int verbosemode;/* * XXX: Fetch our Ethernet address from the ID prom */myetheraddr(ea) struct ether_addr *ea;{#ifdef TRACE extern int trace;#endif TRACE struct idprom id;#ifdef TRACE if (trace >= 10) printf("myetheraddr\n");#endif TRACE if (idprom(IDFORM_1, &id) != IDFORM_1) { printf("ERROR: Missing or invalid ID PROM.\n"); return; } *ea = *(struct ether_addr *)id.id_ether;}/* * Initialize IP state. Find out our Ethernet address and call Reverse ARP * to find out our Internet address. Set the ARP cache to the broadcast host. */inet_init(sip, sain, tmpbuf) register struct saioreq *sip; register struct sainet *sain; char *tmpbuf;{#ifdef TRACE extern int trace;#endif TRACE#ifdef TRACE if (trace >= 10) printf("inet_init\n");#endif TRACE /* get MAC address */#ifdef OPENPROMS (*sip->si_sif->sif_macaddr)(sip->si_devdata, &sain->sain_myether);#else (*sip->si_sif->sif_macaddr)(&sain->sain_myether);#endif bzero((caddr_t)&sain->sain_myaddr, sizeof (struct in_addr)); bzero((caddr_t)&sain->sain_hisaddr, sizeof (struct in_addr)); sain->sain_hisether = etherbroadcastaddr; revarp(sip, sain, tmpbuf); /* Get Internet address. */}/* * Output an IP packet * Cause ARP to be invoked if necessary */ip_output(sip, buf, len, sain, tmpbuf) register struct saioreq *sip; caddr_t buf, tmpbuf; short len; register struct sainet *sain;{#ifdef TRACE extern int trace;#endif TRACE extern unsigned short ipcksum(); register struct ether_header *eh; register struct ip *ip;#ifdef TRACE if (trace >= 10) printf("ip_output\n");#endif TRACE eh = (struct ether_header *)buf; ip = (struct ip *)(buf + sizeof (struct ether_header)); if (bcmp((caddr_t)&ip->ip_dst, (caddr_t)&sain->sain_hisaddr, sizeof (struct in_addr)) != 0) { bcopy((caddr_t)&ip->ip_dst, (caddr_t)&sain->sain_hisaddr, sizeof (struct in_addr)); arp(sip, sain, tmpbuf); } eh->ether_type = ETHERTYPE_IP; eh->ether_shost = sain->sain_myether; eh->ether_dhost = sain->sain_hisether; /* * Checksum the packet. */ ip->ip_sum = 0; ip->ip_sum = ipcksum((caddr_t)ip, sizeof (struct ip)); if (len < ETHERMIN + sizeof (struct ether_header)) { len = ETHERMIN + sizeof (struct ether_header); } return (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, len);}/* * Check incoming packets for IP packets addressed to us. * Also, respond to ARP packets that wish to know about us. * Returns a length for any IP packet addressed to us, 0 otherwise. */ip_input(sip, buf, sain) register struct saioreq *sip; caddr_t buf; register struct sainet *sain;{#ifdef TRACE extern int trace;#endif TRACE register short len; register struct ether_header *eh; register struct ip *ip; register struct ether_arp *ea;#ifdef TRACE if (trace >= 10) printf("ip_input\n");#endif TRACE len = (*sip->si_sif->sif_poll)(sip->si_devdata, buf); eh = (struct ether_header *)buf; if (eh->ether_type == ETHERTYPE_IP && len >= sizeof (struct ether_header)+sizeof (struct ip)) { ip = (struct ip *)(buf + sizeof (struct ether_header));#ifdef NOREVARP if ((sain->sain_hisaddr.s_addr & 0xFF000000) == 0 && bcmp((caddr_t)ðerbroadcastaddr, (caddr_t)&eh->ether_dhost, sizeof (struct ether_addr)) != 0 && (in_broadaddr(sain->sain_hisaddr) || in_lnaof(ip->ip_src) == in_lnaof(sain->sain_hisaddr))) { sain->sain_myaddr = ip->ip_dst; sain->sain_hisaddr = ip->ip_src; sain->sain_hisether = eh->ether_shost; }#endif if (bcmp((caddr_t)&ip->ip_dst, (caddr_t)&sain->sain_myaddr, sizeof (struct in_addr)) != 0) return (0); return (len); } if (eh->ether_type == ETHERTYPE_ARP && len >= sizeof (struct ether_header) + sizeof (struct ether_arp)) { ea = (struct ether_arp *)(buf + sizeof (struct ether_header)); if (ea->arp_pro != ETHERTYPE_IP) return (0); if (bcmp((caddr_t)ea->arp_spa, (caddr_t)&sain->sain_hisaddr, sizeof (struct in_addr)) == 0) sain->sain_hisether = ea->arp_sha; if (ea->arp_op == ARPOP_REQUEST && (bcmp((caddr_t)ea->arp_tpa, (caddr_t)&sain->sain_myaddr, sizeof (struct in_addr)) == 0)) { ea->arp_op = ARPOP_REPLY; eh->ether_dhost = ea->arp_sha; eh->ether_shost = sain->sain_myether; ea->arp_tha = ea->arp_sha; bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa, sizeof (ea->arp_tpa)); ea->arp_sha = sain->sain_myether; bcopy((caddr_t)&sain->sain_myaddr, (caddr_t)ea->arp_spa, sizeof (ea->arp_spa)); (*sip->si_sif->sif_xmit)(sip->si_devdata, buf, sizeof (struct arp_packet)); } return (0); } return (0);}/* * arp * Broadcasts to determine Ethernet address given IP address * See RFC 826 */arp(sip, sain, tmpbuf) register struct saioreq *sip; register struct sainet *sain; char *tmpbuf;{#ifdef TRACE extern int trace;#endif TRACE struct arp_packet out;#ifdef TRACE if (trace >= 10) printf("arp\n");#endif TRACE if (in_lnaof(sain->sain_hisaddr) == INADDR_ANY || (in_lnaof(sain->sain_hisaddr) & INADDR1_ANY) == INADDR1_ANY) { sain->sain_hisether = etherbroadcastaddr; return; } out.arp_eh.ether_type = ETHERTYPE_ARP; out.arp_ea.arp_op = ARPOP_REQUEST; out.arp_ea.arp_tha = etherbroadcastaddr; /* What we want. */ bcopy((caddr_t)&sain->sain_hisaddr, (caddr_t)out.arp_ea.arp_tpa, sizeof (out.arp_ea.arp_tpa)); comarp(sip, sain, &out, tmpbuf);}/* * Reverse ARP client side. Determine our Internet address given our Ethernet * address. See RFC 903. */revarp(sip, sain, tmpbuf) register struct saioreq *sip; register struct sainet *sain; char *tmpbuf;{#ifdef TRACE extern int trace;#endif TRACE struct arp_packet out;#ifdef TRACE if (trace >= 10) printf("revarp\n");#endif TRACE bzero(&out, sizeof (struct arp_packet));#ifdef NOREVARP bzero((caddr_t)&sain->sain_myaddr, sizeof (struct in_addr)); bcopy((caddr_t)&sain->sain_myether.ether_addr_octet[3], (caddr_t)(&sain->sain_myaddr)+1, 3);#else out.arp_eh.ether_type = ETHERTYPE_REVARP; out.arp_ea.arp_op = REVARP_REQUEST; out.arp_ea.arp_tha = sain->sain_myether; /* What we want to find out... */ bzero(out.arp_ea.arp_tpa, sizeof (struct in_addr)); comarp(sip, sain, &out, tmpbuf);#endif bcopy(&sain->sain_myaddr, &my_in_addr, sizeof (struct in_addr)); return;}/* * Common ARP code. Broadcast the packet and wait for the right response. * Fills in structure 'sain' with the results. */static char *pktprint = "packet ignored: %s\n";comarp(sip, sain, out, tmpbuf) register struct saioreq *sip; register struct sainet *sain; register struct arp_packet *out; char *tmpbuf;{#ifdef TRACE extern int trace;#endif TRACE register struct arp_packet *in=((struct arp_packet *) tmpbuf); register int count = 0; register int time = 0; register int len = 0; register int delay = 2; struct in_addr isaddr; /* Required for Sparc */ struct in_addr isaddr2; /* alignment restrictions. */ int timebomb; struct in_addr tmp_ia; int e;#ifdef TRACE if (trace >= 10) printf("comarp\n");#endif TRACE out->arp_eh.ether_dhost = etherbroadcastaddr; out->arp_eh.ether_shost = sain->sain_myether; out->arp_ea.arp_hrd = ARPHRD_ETHER; out->arp_ea.arp_pro = ETHERTYPE_IP; out->arp_ea.arp_hln = sizeof (struct ether_addr); out->arp_ea.arp_pln = sizeof (struct in_addr); out->arp_ea.arp_sha = sain->sain_myether; bcopy((caddr_t)&sain->sain_myaddr, (caddr_t)out->arp_ea.arp_spa, sizeof (out->arp_ea.arp_spa)); for (count=0; /* empty! */; count++) { if ((verbosemode) || (count == WAITCNT)) { if (out->arp_ea.arp_op == ARPOP_REQUEST) { printf("\nRequesting Ethernet address for "); bcopy((caddr_t)out->arp_ea.arp_tpa, (caddr_t)&tmp_ia, sizeof (tmp_ia)); inet_printwhex(tmp_ia); printf("\n"); } else { printf("\nRequesting Internet address for "); ether_print(&out->arp_ea.arp_tha); printf("\n"); } } e = (*sip->si_sif->sif_xmit)(sip->si_devdata, (caddr_t)out, sizeof (*out)); if (!verbosemode) /* show activity */ if (e) printf("X\b"); else feedback(); time = millitime() + (delay * 1000); /* broadcast delay */ while (millitime() <= time) { len = (*sip->si_sif->sif_poll)(sip->si_devdata, tmpbuf); if (verbosemode) if ((len > 0) && (len < used_size)) printf("got short packet - ignored\n"); if (len < used_size) continue; if (verbosemode) { printf("got reply from "); ether_print(&in->arp_eh.ether_shost); printf(" type 0x%x", in->arp_eh.ether_type); printf(" arp_pro 0x%x", in->arp_ea.arp_pro); printf(" arp_sha "); ether_print(&out->arp_ea.arp_sha); printf(" arp_spa "); inet_print(out->arp_ea.arp_spa); printf(" arp_tha "); ether_print(&out->arp_ea.arp_tha); printf(" arp_tpa "); inet_print(out->arp_ea.arp_tpa); printf("\n"); } if (in->arp_ea.arp_pro != ETHERTYPE_IP) { if (verbosemode) printf(pktprint, "wrong arp_pro"); continue; } if (out->arp_ea.arp_op == ARPOP_REQUEST) { if (in->arp_eh.ether_type != ETHERTYPE_ARP) { if (verbosemode) printf(pktprint, "wrong type"); continue; } if (in->arp_ea.arp_op != ARPOP_REPLY) { if (verbosemode) printf(pktprint, "wrong arp_op"); continue; } if (bcmp((caddr_t)in->arp_ea.arp_spa, (caddr_t)out->arp_ea.arp_tpa, sizeof (struct in_addr)) != 0) { if (verbosemode) printf(pktprint, "wrong arp_spa"); continue; } else if ((verbosemode) || (count > WAITCNT)) { printf("Found at "); ether_print(&in->arp_ea.arp_sha); printf("\n"); } sain->sain_hisether = in->arp_ea.arp_sha; return; } else { /* Reverse ARP */ if (in->arp_eh.ether_type != ETHERTYPE_REVARP) { if (verbosemode) printf(pktprint, "wrong type"); continue; } if (in->arp_ea.arp_op != REVARP_REPLY) { if (verbosemode) printf(pktprint, "wrong arp_op"); continue; } if (bcmp((caddr_t)&in->arp_ea.arp_tha, (caddr_t)&out->arp_ea.arp_tha, sizeof (struct ether_addr)) != 0) { if (verbosemode) printf(pktprint, "wrong arp_tha"); continue; } printf("Using IP Address "); bcopy((caddr_t)in->arp_ea.arp_tpa, (caddr_t)&tmp_ia, sizeof (tmp_ia)); inet_printwhex(tmp_ia); printf("\n"); bcopy((caddr_t)in->arp_ea.arp_tpa, (caddr_t)&sain->sain_myaddr, sizeof (sain->sain_myaddr)); /* * Short circuit first ARP. */ bcopy((caddr_t)in->arp_ea.arp_spa, (caddr_t)&sain->sain_hisaddr, sizeof (sain->sain_hisaddr)); sain->sain_hisether = in->arp_ea.arp_sha; return; } } delay = delay * 2; /* Double the request delay */ if (delay > 64) /* maximum delay is 64 seconds */ delay = 64; if (verbosemode) printf("timed out, new delay %d sec\n", delay); (*sip->si_sif->sif_reset)(sip->si_devdata); } /* NOTREACHED */}/* * Return the host portion of an internet address. */u_longin_lnaof(in) struct in_addr in;{ register u_long i = ntohl(in.s_addr); if (IN_CLASSA(i)) return ((i)&IN_CLASSA_HOST); else if (IN_CLASSB(i)) return ((i)&IN_CLASSB_HOST); else return ((i)&IN_CLASSC_HOST);}/* * Test for broadcast IP address */in_broadaddr(in) struct in_addr in;{ register u_long i = ntohl(in.s_addr); if (IN_CLASSA(i)) { i &= IN_CLASSA_HOST; return (i == 0 || i == 0xFFFFFF); } else if (IN_CLASSB(i)) { i &= IN_CLASSB_HOST; return (i == 0 || i == 0xFFFF); } else if (IN_CLASSC(i)) { i &= IN_CLASSC_HOST; return (i == 0 || i == 0xFF); } else return (0); /*NOTREACHED*/}/* * Compute one's complement checksum for IP packet headers. */unsigned shortipcksum(cp, count) caddr_t cp; register int count;{#ifdef TRACE extern int trace;#endif TRACE register unsigned short *sp=((unsigned short *) cp); register unsigned long sum=0; register unsigned long oneword=0x00010000;#ifdef TRACE if (trace >= 10) printf("ipcksum\n");#endif TRACE if (count == 0) return (0); count >>= 1; while (count--) { sum += *sp++; if (sum >= oneword) { /* Wrap carries into low bit. */ sum -= oneword; sum++; } } return (~sum);}inet_printwhex(s) struct in_addr s;{#ifdef TRACE extern int trace;#endif TRACE int len=2;#ifdef TRACE if (trace >= 10) printf("inet_print\n");#endif TRACE printf("%d.%d.%d.%d = ", s.S_un.S_un_b.s_b1, s.S_un.S_un_b.s_b2, s.S_un.S_un_b.s_b3, s.S_un.S_un_b.s_b4); printhex(s.S_un.S_un_b.s_b1, len); printhex(s.S_un.S_un_b.s_b2, len); printhex(s.S_un.S_un_b.s_b3, len); printhex(s.S_un.S_un_b.s_b4, len);}inet_print(s) struct in_addr s;{ printf("%d.%d.%d.%d", s.S_un.S_un_b.s_b1, s.S_un.S_un_b.s_b2, s.S_un.S_un_b.s_b3, s.S_un.S_un_b.s_b4);}ether_print(ea) struct ether_addr *ea;{#ifndef TRACE extern int trace;#endif TRACE register u_char *p = (&ea->ether_addr_octet[0]);#ifdef TRACE if (trace >= 10) printf("ether_print\n");#endif TRACE printf("%x:%x:%x:%x:%x:%x", p[0], p[1], p[2], p[3], p[4], p[5]);}char chardigs[]="0123456789ABCDEF";/* * printhex() prints rightmost <digs> hex digits of <val> */printhex(val, digs) register int val; register int digs;{ digs = ((digs-1)&7)<<2; /* digs == 0 => print 8 digits */ for (; digs >= 0; digs-=4) putchar(chardigs[(val>>digs)&0xF]);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?