Thread View: comp.bugs.4bsd.ucb-fixes
1 messages
1 total messages
Started by Keith Bostic
Tue, 05 Apr 1988 03:18
V1.49 ((inet 3 of 4) updated IP/TCP and XNS sources for 4.3BSD)
Author: Keith Bostic
Date: Tue, 05 Apr 1988 03:18
Date: Tue, 05 Apr 1988 03:18
2099 lines
59633 bytes
59633 bytes
Subject: (inet 3 of 4) updated IP/TCP and XNS sources for 4.3BSD
Index: sys 4.3BSD
Description:
This is number 4 of 11 total articles posted to the newsgroup
comp.bugs.4bsd.ucb-fixes. This archive is number 3 of the 4
articles that make up the inet posting.
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# netinet
# netinet/icmp_var.h
# netinet/if_ether.c
# netinet/if_ether.h
# netinet/in.c
# netinet/in.h
# netinet/in_cksum.c
# netinet/in_pcb.c
# netinet/in_pcb.h
# netinet/in_proto.c
# netinet/in_systm.h
# netinet/in_var.h
#
echo c - netinet
mkdir netinet > /dev/null 2>&1
echo x - netinet/icmp_var.h
sed 's/^X//' >netinet/icmp_var.h << 'END-of-netinet/icmp_var.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)icmp_var.h 7.3 (Berkeley) 12/7/87
X */
X
X/*
X * Variables related to this implementation
X * of the internet control message protocol.
X */
Xstruct icmpstat {
X/* statistics related to icmp packets generated */
X int icps_error; /* # of calls to icmp_error */
X int icps_oldshort; /* no error 'cuz old ip too short */
X int icps_oldicmp; /* no error 'cuz old was icmp */
X int icps_outhist[ICMP_MAXTYPE + 1];
X/* statistics related to input messages processed */
X int icps_badcode; /* icmp_code out of range */
X int icps_tooshort; /* packet < ICMP_MINLEN */
X int icps_checksum; /* bad checksum */
X int icps_badlen; /* calculated bound mismatch */
X int icps_reflect; /* number of responses */
X int icps_inhist[ICMP_MAXTYPE + 1];
X};
X
X#ifdef KERNEL
Xstruct icmpstat icmpstat;
X#endif
END-of-netinet/icmp_var.h
echo x - netinet/if_ether.c
sed 's/^X//' >netinet/if_ether.c << 'END-of-netinet/if_ether.c'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)if_ether.c 7.6 (Berkeley) 12/7/87
X */
X
X/*
X * Ethernet address resolution protocol.
X * TODO:
X * run at splnet (add ARP protocol intr.)
X * link entries onto hash chains, keep free list
X * add "inuse/lock" bit (or ref. count) along with valid bit
X */
X
X#include "param.h"
X#include "systm.h"
X#include "mbuf.h"
X#include "socket.h"
X#include "time.h"
X#include "kernel.h"
X#include "errno.h"
X#include "ioctl.h"
X#include "syslog.h"
X
X#include "../net/if.h"
X#include "in.h"
X#include "in_systm.h"
X#include "ip.h"
X#include "if_ether.h"
X
X#ifdef GATEWAY
X#define ARPTAB_BSIZ 16 /* bucket size */
X#define ARPTAB_NB 37 /* number of buckets */
X#else
X#define ARPTAB_BSIZ 9 /* bucket size */
X#define ARPTAB_NB 19 /* number of buckets */
X#endif
X#define ARPTAB_SIZE (ARPTAB_BSIZ * ARPTAB_NB)
Xstruct arptab arptab[ARPTAB_SIZE];
Xint arptab_size = ARPTAB_SIZE; /* for arp command */
X
X/*
X * ARP trailer negotiation. Trailer protocol is not IP specific,
X * but ARP request/response use IP addresses.
X */
X#define ETHERTYPE_IPTRAILERS ETHERTYPE_TRAIL
X
X#define ARPTAB_HASH(a) \
X ((u_long)(a) % ARPTAB_NB)
X
X#define ARPTAB_LOOK(at,addr) { \
X register n; \
X at = &arptab[ARPTAB_HASH(addr) * ARPTAB_BSIZ]; \
X for (n = 0 ; n < ARPTAB_BSIZ ; n++,at++) \
X if (at->at_iaddr.s_addr == addr) \
X break; \
X if (n >= ARPTAB_BSIZ) \
X at = 0; \
X}
X
X/* timer values */
X#define ARPT_AGE (60*1) /* aging timer, 1 min. */
X#define ARPT_KILLC 20 /* kill completed entry in 20 mins. */
X#define ARPT_KILLI 3 /* kill incomplete entry in 3 minutes */
X
Xu_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
Xextern struct ifnet loif;
X
X/*
X * Timeout routine. Age arp_tab entries once a minute.
X */
Xarptimer()
X{
X register struct arptab *at;
X register i;
X
X timeout(arptimer, (caddr_t)0, ARPT_AGE * hz);
X at = &arptab[0];
X for (i = 0; i < ARPTAB_SIZE; i++, at++) {
X if (at->at_flags == 0 || (at->at_flags & ATF_PERM))
X continue;
X if (++at->at_timer < ((at->at_flags&ATF_COM) ?
X ARPT_KILLC : ARPT_KILLI))
X continue;
X /* timer has expired, clear entry */
X arptfree(at);
X }
X}
X
X/*
X * Broadcast an ARP packet, asking who has addr on interface ac.
X */
Xarpwhohas(ac, addr)
X register struct arpcom *ac;
X struct in_addr *addr;
X{
X register struct mbuf *m;
X register struct ether_header *eh;
X register struct ether_arp *ea;
X struct sockaddr sa;
X
X if ((m = m_get(M_DONTWAIT, MT_DATA)) == NULL)
X return;
X m->m_len = sizeof *ea;
X m->m_off = MMAXOFF - m->m_len;
X ea = mtod(m, struct ether_arp *);
X eh = (struct ether_header *)sa.sa_data;
X bzero((caddr_t)ea, sizeof (*ea));
X bcopy((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost,
X sizeof(eh->ether_dhost));
X eh->ether_type = ETHERTYPE_ARP; /* if_output will swap */
X ea->arp_hrd = htons(ARPHRD_ETHER);
X ea->arp_pro = htons(ETHERTYPE_IP);
X ea->arp_hln = sizeof(ea->arp_sha); /* hardware address length */
X ea->arp_pln = sizeof(ea->arp_spa); /* protocol address length */
X ea->arp_op = htons(ARPOP_REQUEST);
X bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
X sizeof(ea->arp_sha));
X bcopy((caddr_t)&ac->ac_ipaddr, (caddr_t)ea->arp_spa,
X sizeof(ea->arp_spa));
X bcopy((caddr_t)addr, (caddr_t)ea->arp_tpa, sizeof(ea->arp_tpa));
X sa.sa_family = AF_UNSPEC;
X (*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
X}
X
Xint useloopback = 1; /* use loopback interface for local traffic */
X
X/*
X * Resolve an IP address into an ethernet address. If success,
X * desten is filled in. If there is no entry in arptab,
X * set one up and broadcast a request for the IP address.
X * Hold onto this mbuf and resend it once the address
X * is finally resolved. A return value of 1 indicates
X * that desten has been filled in and the packet should be sent
X * normally; a 0 return indicates that the packet has been
X * taken over here, either now or for later transmission.
X *
X * We do some (conservative) locking here at splimp, since
X * arptab is also altered from input interrupt service (ecintr/ilintr
X * calls arpinput when ETHERTYPE_ARP packets come in).
X */
Xarpresolve(ac, m, destip, desten, usetrailers)
X register struct arpcom *ac;
X struct mbuf *m;
X register struct in_addr *destip;
X register u_char *desten;
X int *usetrailers;
X{
X register struct arptab *at;
X struct sockaddr_in sin;
X u_long lna;
X int s;
X
X *usetrailers = 0;
X if (in_broadcast(*destip)) { /* broadcast address */
X bcopy((caddr_t)etherbroadcastaddr, (caddr_t)desten,
X sizeof(etherbroadcastaddr));
X return (1);
X }
X lna = in_lnaof(*destip);
X /* if for us, use software loopback driver if up */
X if (destip->s_addr == ac->ac_ipaddr.s_addr) {
X /*
X * This test used to be
X * if (loif.if_flags & IFF_UP)
X * It allowed local traffic to be forced
X * through the hardware by configuring the loopback down.
X * However, it causes problems during network configuration
X * for boards that can't receive packets they send.
X * It is now necessary to clear "useloopback"
X * to force traffic out to the hardware.
X */
X if (useloopback) {
X sin.sin_family = AF_INET;
X sin.sin_addr = *destip;
X (void) looutput(&loif, m, (struct sockaddr *)&sin);
X /*
X * The packet has already been sent and freed.
X */
X return (0);
X } else {
X bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten,
X sizeof(ac->ac_enaddr));
X return (1);
X }
X }
X s = splimp();
X ARPTAB_LOOK(at, destip->s_addr);
X if (at == 0) { /* not found */
X if (ac->ac_if.if_flags & IFF_NOARP) {
X bcopy((caddr_t)ac->ac_enaddr, (caddr_t)desten, 3);
X desten[3] = (lna >> 16) & 0x7f;
X desten[4] = (lna >> 8) & 0xff;
X desten[5] = lna & 0xff;
X splx(s);
X return (1);
X } else {
X at = arptnew(destip);
X if (at == 0)
X panic("arpresolve: no free entry");
X at->at_hold = m;
X arpwhohas(ac, destip);
X splx(s);
X return (0);
X }
X }
X at->at_timer = 0; /* restart the timer */
X if (at->at_flags & ATF_COM) { /* entry IS complete */
X bcopy((caddr_t)at->at_enaddr, (caddr_t)desten,
X sizeof(at->at_enaddr));
X if (at->at_flags & ATF_USETRAILERS)
X *usetrailers = 1;
X splx(s);
X return (1);
X }
X /*
X * There is an arptab entry, but no ethernet address
X * response yet. Replace the held mbuf with this
X * latest one.
X */
X if (at->at_hold)
X m_freem(at->at_hold);
X at->at_hold = m;
X arpwhohas(ac, destip); /* ask again */
X splx(s);
X return (0);
X}
X
X/*
X * Called from 10 Mb/s Ethernet interrupt handlers
X * when ether packet type ETHERTYPE_ARP
X * is received. Common length and type checks are done here,
X * then the protocol-specific routine is called.
X */
Xarpinput(ac, m)
X struct arpcom *ac;
X struct mbuf *m;
X{
X register struct arphdr *ar;
X
X if (ac->ac_if.if_flags & IFF_NOARP)
X goto out;
X IF_ADJ(m);
X if (m->m_len < sizeof(struct arphdr))
X goto out;
X ar = mtod(m, struct arphdr *);
X if (ntohs(ar->ar_hrd) != ARPHRD_ETHER)
X goto out;
X if (m->m_len < sizeof(struct arphdr) + 2 * ar->ar_hln + 2 * ar->ar_pln)
X goto out;
X
X switch (ntohs(ar->ar_pro)) {
X
X case ETHERTYPE_IP:
X case ETHERTYPE_IPTRAILERS:
X in_arpinput(ac, m);
X return;
X
X default:
X break;
X }
Xout:
X m_freem(m);
X}
X
X/*
X * ARP for Internet protocols on 10 Mb/s Ethernet.
X * Algorithm is that given in RFC 826.
X * In addition, a sanity check is performed on the sender
X * protocol address, to catch impersonators.
X * We also handle negotiations for use of trailer protocol:
X * ARP replies for protocol type ETHERTYPE_TRAIL are sent
X * along with IP replies if we want trailers sent to us,
X * and also send them in response to IP replies.
X * This allows either end to announce the desire to receive
X * trailer packets.
X * We reply to requests for ETHERTYPE_TRAIL protocol as well,
X * but don't normally send requests.
X */
Xin_arpinput(ac, m)
X register struct arpcom *ac;
X struct mbuf *m;
X{
X register struct ether_arp *ea;
X struct ether_header *eh;
X register struct arptab *at; /* same as "merge" flag */
X struct mbuf *mcopy = 0;
X struct sockaddr_in sin;
X struct sockaddr sa;
X struct in_addr isaddr, itaddr, myaddr;
X int proto, op, s, completed = 0;
X
X myaddr = ac->ac_ipaddr;
X ea = mtod(m, struct ether_arp *);
X proto = ntohs(ea->arp_pro);
X op = ntohs(ea->arp_op);
X bcopy((caddr_t)ea->arp_spa, (caddr_t)&isaddr, sizeof (isaddr));
X bcopy((caddr_t)ea->arp_tpa, (caddr_t)&itaddr, sizeof (itaddr));
X if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)ac->ac_enaddr,
X sizeof (ea->arp_sha)))
X goto out; /* it's from me, ignore it. */
X if (!bcmp((caddr_t)ea->arp_sha, (caddr_t)etherbroadcastaddr,
X sizeof (ea->arp_sha))) {
X log(LOG_ERR,
X "arp: ether address is broadcast for IP address %x!\n",
X ntohl(isaddr.s_addr));
X goto out;
X }
X if (isaddr.s_addr == myaddr.s_addr) {
X log(LOG_ERR, "%s: %s\n",
X "duplicate IP address!! sent from ethernet address",
X ether_sprintf(ea->arp_sha));
X itaddr = myaddr;
X if (op == ARPOP_REQUEST)
X goto reply;
X goto out;
X }
X s = splimp();
X ARPTAB_LOOK(at, isaddr.s_addr);
X if (at) {
X bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
X sizeof(ea->arp_sha));
X if ((at->at_flags & ATF_COM) == 0)
X completed = 1;
X at->at_flags |= ATF_COM;
X if (at->at_hold) {
X sin.sin_family = AF_INET;
X sin.sin_addr = isaddr;
X (*ac->ac_if.if_output)(&ac->ac_if,
X at->at_hold, (struct sockaddr *)&sin);
X at->at_hold = 0;
X }
X }
X if (at == 0 && itaddr.s_addr == myaddr.s_addr) {
X /* ensure we have a table entry */
X if (at = arptnew(&isaddr)) {
X bcopy((caddr_t)ea->arp_sha, (caddr_t)at->at_enaddr,
X sizeof(ea->arp_sha));
X completed = 1;
X at->at_flags |= ATF_COM;
X }
X }
X splx(s);
Xreply:
X switch (proto) {
X
X case ETHERTYPE_IPTRAILERS:
X /* partner says trailers are OK */
X if (at)
X at->at_flags |= ATF_USETRAILERS;
X /*
X * Reply to request iff we want trailers.
X */
X if (op != ARPOP_REQUEST || ac->ac_if.if_flags & IFF_NOTRAILERS)
X goto out;
X break;
X
X case ETHERTYPE_IP:
X /*
X * Reply if this is an IP request,
X * or if we want to send a trailer response.
X * Send the latter only to the IP response
X * that completes the current ARP entry.
X */
X if (op != ARPOP_REQUEST &&
X (completed == 0 || ac->ac_if.if_flags & IFF_NOTRAILERS))
X goto out;
X }
X if (itaddr.s_addr == myaddr.s_addr) {
X /* I am the target */
X bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
X sizeof(ea->arp_sha));
X bcopy((caddr_t)ac->ac_enaddr, (caddr_t)ea->arp_sha,
X sizeof(ea->arp_sha));
X } else {
X ARPTAB_LOOK(at, itaddr.s_addr);
X if (at == NULL || (at->at_flags & ATF_PUBL) == 0)
X goto out;
X bcopy((caddr_t)ea->arp_sha, (caddr_t)ea->arp_tha,
X sizeof(ea->arp_sha));
X bcopy((caddr_t)at->at_enaddr, (caddr_t)ea->arp_sha,
X sizeof(ea->arp_sha));
X }
X
X bcopy((caddr_t)ea->arp_spa, (caddr_t)ea->arp_tpa,
X sizeof(ea->arp_spa));
X bcopy((caddr_t)&itaddr, (caddr_t)ea->arp_spa,
X sizeof(ea->arp_spa));
X ea->arp_op = htons(ARPOP_REPLY);
X /*
X * If incoming packet was an IP reply,
X * we are sending a reply for type IPTRAILERS.
X * If we are sending a reply for type IP
X * and we want to receive trailers,
X * send a trailer reply as well.
X */
X if (op == ARPOP_REPLY)
X ea->arp_pro = htons(ETHERTYPE_IPTRAILERS);
X else if (proto == ETHERTYPE_IP &&
X (ac->ac_if.if_flags & IFF_NOTRAILERS) == 0)
X mcopy = m_copy(m, 0, (int)M_COPYALL);
X eh = (struct ether_header *)sa.sa_data;
X bcopy((caddr_t)ea->arp_tha, (caddr_t)eh->ether_dhost,
X sizeof(eh->ether_dhost));
X eh->ether_type = ETHERTYPE_ARP;
X sa.sa_family = AF_UNSPEC;
X (*ac->ac_if.if_output)(&ac->ac_if, m, &sa);
X if (mcopy) {
X ea = mtod(mcopy, struct ether_arp *);
X ea->arp_pro = htons(ETHERTYPE_IPTRAILERS);
X (*ac->ac_if.if_output)(&ac->ac_if, mcopy, &sa);
X }
X return;
Xout:
X m_freem(m);
X return;
X}
X
X/*
X * Free an arptab entry.
X */
Xarptfree(at)
X register struct arptab *at;
X{
X int s = splimp();
X
X if (at->at_hold)
X m_freem(at->at_hold);
X at->at_hold = 0;
X at->at_timer = at->at_flags = 0;
X at->at_iaddr.s_addr = 0;
X splx(s);
X}
X
X/*
X * Enter a new address in arptab, pushing out the oldest entry
X * from the bucket if there is no room.
X * This always succeeds since no bucket can be completely filled
X * with permanent entries (except from arpioctl when testing whether
X * another permanent entry will fit).
X * MUST BE CALLED AT SPLIMP.
X */
Xstruct arptab *
Xarptnew(addr)
X struct in_addr *addr;
X{
X register n;
X int oldest = -1;
X register struct arptab *at, *ato = NULL;
X static int first = 1;
X
X if (first) {
X first = 0;
X timeout(arptimer, (caddr_t)0, hz);
X }
X at = &arptab[ARPTAB_HASH(addr->s_addr) * ARPTAB_BSIZ];
X for (n = 0; n < ARPTAB_BSIZ; n++,at++) {
X if (at->at_flags == 0)
X goto out; /* found an empty entry */
X if (at->at_flags & ATF_PERM)
X continue;
X if ((int) at->at_timer > oldest) {
X oldest = at->at_timer;
X ato = at;
X }
X }
X if (ato == NULL)
X return (NULL);
X at = ato;
X arptfree(at);
Xout:
X at->at_iaddr = *addr;
X at->at_flags = ATF_INUSE;
X return (at);
X}
X
Xarpioctl(cmd, data)
X int cmd;
X caddr_t data;
X{
X register struct arpreq *ar = (struct arpreq *)data;
X register struct arptab *at;
X register struct sockaddr_in *sin;
X int s;
X
X if (ar->arp_pa.sa_family != AF_INET ||
X ar->arp_ha.sa_family != AF_UNSPEC)
X return (EAFNOSUPPORT);
X sin = (struct sockaddr_in *)&ar->arp_pa;
X s = splimp();
X ARPTAB_LOOK(at, sin->sin_addr.s_addr);
X if (at == NULL) { /* not found */
X if (cmd != SIOCSARP) {
X splx(s);
X return (ENXIO);
X }
X if (ifa_ifwithnet(&ar->arp_pa) == NULL) {
X splx(s);
X return (ENETUNREACH);
X }
X }
X switch (cmd) {
X
X case SIOCSARP: /* set entry */
X if (at == NULL) {
X at = arptnew(&sin->sin_addr);
X if (at == NULL) {
X splx(s);
X return (EADDRNOTAVAIL);
X }
X if (ar->arp_flags & ATF_PERM) {
X /* never make all entries in a bucket permanent */
X register struct arptab *tat;
X
X /* try to re-allocate */
X tat = arptnew(&sin->sin_addr);
X if (tat == NULL) {
X arptfree(at);
X splx(s);
X return (EADDRNOTAVAIL);
X }
X arptfree(tat);
X }
X }
X bcopy((caddr_t)ar->arp_ha.sa_data, (caddr_t)at->at_enaddr,
X sizeof(at->at_enaddr));
X at->at_flags = ATF_COM | ATF_INUSE |
X (ar->arp_flags & (ATF_PERM|ATF_PUBL|ATF_USETRAILERS));
X at->at_timer = 0;
X break;
X
X case SIOCDARP: /* delete entry */
X arptfree(at);
X break;
X
X case SIOCGARP: /* get entry */
X bcopy((caddr_t)at->at_enaddr, (caddr_t)ar->arp_ha.sa_data,
X sizeof(at->at_enaddr));
X ar->arp_flags = at->at_flags;
X break;
X }
X splx(s);
X return (0);
X}
X
X/*
X * Convert Ethernet address to printable (loggable) representation.
X */
Xchar *
Xether_sprintf(ap)
X register u_char *ap;
X{
X register i;
X static char etherbuf[18];
X register char *cp = etherbuf;
X static char digits[] = "0123456789abcdef";
X
X for (i = 0; i < 6; i++) {
X *cp++ = digits[*ap >> 4];
X *cp++ = digits[*ap++ & 0xf];
X *cp++ = ':';
X }
X *--cp = 0;
X return (etherbuf);
X}
END-of-netinet/if_ether.c
echo x - netinet/if_ether.h
sed 's/^X//' >netinet/if_ether.h << 'END-of-netinet/if_ether.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)if_ether.h 7.2 (Berkeley) 12/7/87
X */
X
X/*
X * Structure of a 10Mb/s Ethernet header.
X */
Xstruct ether_header {
X u_char ether_dhost[6];
X u_char ether_shost[6];
X u_short ether_type;
X};
X
X#define ETHERTYPE_PUP 0x0200 /* PUP protocol */
X#define ETHERTYPE_IP 0x0800 /* IP protocol */
X#define ETHERTYPE_ARP 0x0806 /* Addr. resolution protocol */
X
X/*
X * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
X * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
X * by an ETHER type (as given above) and then the (variable-length) header.
X */
X#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */
X#define ETHERTYPE_NTRAILER 16
X
X#define ETHERMTU 1500
X#define ETHERMIN (60-14)
X
X/*
X * Ethernet Address Resolution Protocol.
X *
X * See RFC 826 for protocol description. Structure below is adapted
X * to resolving internet addresses. Field names used correspond to
X * RFC 826.
X */
Xstruct ether_arp {
X struct arphdr ea_hdr; /* fixed-size header */
X u_char arp_sha[6]; /* sender hardware address */
X u_char arp_spa[4]; /* sender protocol address */
X u_char arp_tha[6]; /* target hardware address */
X u_char arp_tpa[4]; /* target protocol address */
X};
X#define arp_hrd ea_hdr.ar_hrd
X#define arp_pro ea_hdr.ar_pro
X#define arp_hln ea_hdr.ar_hln
X#define arp_pln ea_hdr.ar_pln
X#define arp_op ea_hdr.ar_op
X
X
X/*
X * Structure shared between the ethernet driver modules and
X * the address resolution code. For example, each ec_softc or il_softc
X * begins with this structure.
X */
Xstruct arpcom {
X struct ifnet ac_if; /* network-visible interface */
X u_char ac_enaddr[6]; /* ethernet hardware address */
X struct in_addr ac_ipaddr; /* copy of ip address- XXX */
X};
X
X/*
X * Internet to ethernet address resolution table.
X */
Xstruct arptab {
X struct in_addr at_iaddr; /* internet address */
X u_char at_enaddr[6]; /* ethernet address */
X u_char at_timer; /* minutes since last reference */
X u_char at_flags; /* flags */
X struct mbuf *at_hold; /* last packet until resolved/timeout */
X};
X
X#ifdef KERNEL
Xu_char etherbroadcastaddr[6];
Xstruct arptab *arptnew();
Xchar *ether_sprintf();
X#endif
END-of-netinet/if_ether.h
echo x - netinet/in.c
sed 's/^X//' >netinet/in.c << 'END-of-netinet/in.c'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)in.c 7.7 (Berkeley) 4/3/88
X */
X
X#include "param.h"
X#include "ioctl.h"
X#include "mbuf.h"
X#include "protosw.h"
X#include "socket.h"
X#include "socketvar.h"
X#include "uio.h"
X#include "dir.h"
X#include "user.h"
X#include "in_systm.h"
X#include "../net/if.h"
X#include "../net/route.h"
X#include "../net/af.h"
X#include "in.h"
X#include "in_var.h"
X
X#ifdef INET
Xinet_hash(sin, hp)
X register struct sockaddr_in *sin;
X struct afhash *hp;
X{
X register u_long n;
X
X n = in_netof(sin->sin_addr);
X if (n)
X while ((n & 0xff) == 0)
X n >>= 8;
X hp->afh_nethash = n;
X hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
X}
X
Xinet_netmatch(sin1, sin2)
X struct sockaddr_in *sin1, *sin2;
X{
X
X return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
X}
X
X/*
X * Formulate an Internet address from network + host.
X */
Xstruct in_addr
Xin_makeaddr(net, host)
X u_long net, host;
X{
X register struct in_ifaddr *ia;
X register u_long mask;
X u_long addr;
X
X if (IN_CLASSA(net))
X mask = IN_CLASSA_HOST;
X else if (IN_CLASSB(net))
X mask = IN_CLASSB_HOST;
X else
X mask = IN_CLASSC_HOST;
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if ((ia->ia_netmask & net) == ia->ia_net) {
X mask = ~ia->ia_subnetmask;
X break;
X }
X addr = htonl(net | (host & mask));
X return (*(struct in_addr *)&addr);
X}
X
X/*
X * Return the network number from an internet address.
X */
Xu_long
Xin_netof(in)
X struct in_addr in;
X{
X register u_long i = ntohl(in.s_addr);
X register u_long net;
X register struct in_ifaddr *ia;
X
X if (IN_CLASSA(i))
X net = i & IN_CLASSA_NET;
X else if (IN_CLASSB(i))
X net = i & IN_CLASSB_NET;
X else if (IN_CLASSC(i))
X net = i & IN_CLASSC_NET;
X else
X return (0);
X
X /*
X * Check whether network is a subnet;
X * if so, return subnet number.
X */
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if (net == ia->ia_net)
X return (i & ia->ia_subnetmask);
X return (net);
X}
X
X/*
X * Return the host portion of an internet address.
X */
Xu_long
Xin_lnaof(in)
X struct in_addr in;
X{
X register u_long i = ntohl(in.s_addr);
X register u_long net, host;
X register struct in_ifaddr *ia;
X
X if (IN_CLASSA(i)) {
X net = i & IN_CLASSA_NET;
X host = i & IN_CLASSA_HOST;
X } else if (IN_CLASSB(i)) {
X net = i & IN_CLASSB_NET;
X host = i & IN_CLASSB_HOST;
X } else if (IN_CLASSC(i)) {
X net = i & IN_CLASSC_NET;
X host = i & IN_CLASSC_HOST;
X } else
X return (i);
X
X /*
X * Check whether network is a subnet;
X * if so, use the modified interpretation of `host'.
X */
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if (net == ia->ia_net)
X return (host &~ ia->ia_subnetmask);
X return (host);
X}
X
X#ifndef SUBNETSARELOCAL
X#define SUBNETSARELOCAL 1
X#endif
Xint subnetsarelocal = SUBNETSARELOCAL;
X/*
X * Return 1 if an internet address is for a ``local'' host
X * (one to which we have a connection). If subnetsarelocal
X * is true, this includes other subnets of the local net.
X * Otherwise, it includes only the directly-connected (sub)nets.
X */
Xin_localaddr(in)
X struct in_addr in;
X{
X register u_long i = ntohl(in.s_addr);
X register struct in_ifaddr *ia;
X
X if (subnetsarelocal) {
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if ((i & ia->ia_netmask) == ia->ia_net)
X return (1);
X } else {
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if ((i & ia->ia_subnetmask) == ia->ia_subnet)
X return (1);
X }
X return (0);
X}
X
X/*
X * Determine whether an IP address is in a reserved set of addresses
X * that may not be forwarded, or whether datagrams to that destination
X * may be forwarded.
X */
Xin_canforward(in)
X struct in_addr in;
X{
X register u_long i = ntohl(in.s_addr);
X register u_long net;
X
X if (IN_EXPERIMENTAL(i))
X return (0);
X if (IN_CLASSA(i)) {
X net = i & IN_CLASSA_NET;
X if (net == 0 || net == IN_LOOPBACKNET)
X return (0);
X }
X return (1);
X}
X
Xint in_interfaces; /* number of external internet interfaces */
Xextern struct ifnet loif;
X
X/*
X * Generic internet control operations (ioctl's).
X * Ifp is 0 if not an interface-specific ioctl.
X */
X/* ARGSUSED */
Xin_control(so, cmd, data, ifp)
X struct socket *so;
X int cmd;
X caddr_t data;
X register struct ifnet *ifp;
X{
X register struct ifreq *ifr = (struct ifreq *)data;
X register struct in_ifaddr *ia = 0;
X struct ifaddr *ifa;
X struct mbuf *m;
X int error;
X
X /*
X * Find address for this interface, if it exists.
X */
X if (ifp)
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if (ia->ia_ifp == ifp)
X break;
X
X switch (cmd) {
X
X case SIOCSIFADDR:
X case SIOCSIFNETMASK:
X case SIOCSIFDSTADDR:
X if (!suser())
X return (u.u_error);
X
X if (ifp == 0)
X panic("in_control");
X if (ia == (struct in_ifaddr *)0) {
X m = m_getclr(M_WAIT, MT_IFADDR);
X if (m == (struct mbuf *)NULL)
X return (ENOBUFS);
X if (ia = in_ifaddr) {
X for ( ; ia->ia_next; ia = ia->ia_next)
X ;
X ia->ia_next = mtod(m, struct in_ifaddr *);
X } else
X in_ifaddr = mtod(m, struct in_ifaddr *);
X ia = mtod(m, struct in_ifaddr *);
X if (ifa = ifp->if_addrlist) {
X for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
X ;
X ifa->ifa_next = (struct ifaddr *) ia;
X } else
X ifp->if_addrlist = (struct ifaddr *) ia;
X ia->ia_ifp = ifp;
X IA_SIN(ia)->sin_family = AF_INET;
X if (ifp != &loif)
X in_interfaces++;
X }
X break;
X
X case SIOCSIFBRDADDR:
X if (!suser())
X return (u.u_error);
X /* FALLTHROUGH */
X
X default:
X if (ia == (struct in_ifaddr *)0)
X return (EADDRNOTAVAIL);
X break;
X }
X
X switch (cmd) {
X
X case SIOCGIFADDR:
X ifr->ifr_addr = ia->ia_addr;
X break;
X
X case SIOCGIFBRDADDR:
X if ((ifp->if_flags & IFF_BROADCAST) == 0)
X return (EINVAL);
X ifr->ifr_dstaddr = ia->ia_broadaddr;
X break;
X
X case SIOCGIFDSTADDR:
X if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
X return (EINVAL);
X ifr->ifr_dstaddr = ia->ia_dstaddr;
X break;
X
X case SIOCGIFNETMASK:
X#define satosin(sa) ((struct sockaddr_in *)(sa))
X satosin(&ifr->ifr_addr)->sin_family = AF_INET;
X satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask);
X break;
X
X case SIOCSIFDSTADDR:
X {
X struct sockaddr oldaddr;
X
X if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
X return (EINVAL);
X oldaddr = ia->ia_dstaddr;
X ia->ia_dstaddr = ifr->ifr_dstaddr;
X if (ifp->if_ioctl &&
X (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
X ia->ia_dstaddr = oldaddr;
X return (error);
X }
X if (ia->ia_flags & IFA_ROUTE) {
X rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT,
X RTF_HOST);
X rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
X RTF_HOST|RTF_UP);
X }
X }
X break;
X
X case SIOCSIFBRDADDR:
X if ((ifp->if_flags & IFF_BROADCAST) == 0)
X return (EINVAL);
X ia->ia_broadaddr = ifr->ifr_broadaddr;
X break;
X
X case SIOCSIFADDR:
X return (in_ifinit(ifp, ia, &ifr->ifr_addr));
X
X case SIOCSIFNETMASK:
X ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr);
X break;
X
X default:
X if (ifp == 0 || ifp->if_ioctl == 0)
X return (EOPNOTSUPP);
X return ((*ifp->if_ioctl)(ifp, cmd, data));
X }
X return (0);
X}
X
X/*
X * Initialize an interface's internet address
X * and routing table entry.
X */
Xin_ifinit(ifp, ia, sin)
X register struct ifnet *ifp;
X register struct in_ifaddr *ia;
X struct sockaddr_in *sin;
X{
X register u_long i = ntohl(sin->sin_addr.s_addr);
X struct sockaddr oldaddr;
X struct sockaddr_in netaddr;
X int s = splimp(), error;
X
X oldaddr = ia->ia_addr;
X ia->ia_addr = *(struct sockaddr *)sin;
X
X /*
X * Give the interface a chance to initialize
X * if this is its first address,
X * and to validate the address if necessary.
X */
X if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
X splx(s);
X ia->ia_addr = oldaddr;
X return (error);
X }
X
X /*
X * Delete any previous route for an old address.
X */
X bzero((caddr_t)&netaddr, sizeof (netaddr));
X netaddr.sin_family = AF_INET;
X if (ia->ia_flags & IFA_ROUTE) {
X if (ifp->if_flags & IFF_LOOPBACK)
X rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST);
X else if (ifp->if_flags & IFF_POINTOPOINT)
X rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT,
X RTF_HOST);
X else {
X netaddr.sin_addr = in_makeaddr(ia->ia_subnet,
X INADDR_ANY);
X rtinit((struct sockaddr *)&netaddr, &oldaddr,
X (int)SIOCDELRT, 0);
X }
X ia->ia_flags &= ~IFA_ROUTE;
X }
X if (IN_CLASSA(i))
X ia->ia_netmask = IN_CLASSA_NET;
X else if (IN_CLASSB(i))
X ia->ia_netmask = IN_CLASSB_NET;
X else
X ia->ia_netmask = IN_CLASSC_NET;
X ia->ia_net = i & ia->ia_netmask;
X /*
X * The subnet mask includes at least the standard network part,
X * but may already have been set to a larger value.
X */
X ia->ia_subnetmask |= ia->ia_netmask;
X ia->ia_subnet = i & ia->ia_subnetmask;
X if (ifp->if_flags & IFF_BROADCAST) {
X ia->ia_broadaddr.sa_family = AF_INET;
X ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr =
X in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
X ia->ia_netbroadcast.s_addr =
X htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
X }
X /*
X * Add route for the network.
X */
X if (ifp->if_flags & IFF_LOOPBACK)
X rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT,
X RTF_HOST|RTF_UP);
X else if (ifp->if_flags & IFF_POINTOPOINT)
X rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
X RTF_HOST|RTF_UP);
X else {
X netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
X rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
X (int)SIOCADDRT, RTF_UP);
X }
X ia->ia_flags |= IFA_ROUTE;
X splx(s);
X return (0);
X}
X
X/*
X * Return address info for specified internet network.
X */
Xstruct in_ifaddr *
Xin_iaonnetof(net)
X u_long net;
X{
X register struct in_ifaddr *ia;
X
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if (ia->ia_subnet == net)
X return (ia);
X return ((struct in_ifaddr *)0);
X}
X
X/*
X * Return 1 if the address might be a local broadcast address.
X */
Xin_broadcast(in)
X struct in_addr in;
X{
X register struct in_ifaddr *ia;
X u_long t;
X
X /*
X * Look through the list of addresses for a match
X * with a broadcast address.
X */
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
X if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == in.s_addr)
X return (1);
X /*
X * Check for old-style (host 0) broadcast.
X */
X if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
X return (1);
X }
X if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
X return (1);
X return (0);
X}
X#endif
END-of-netinet/in.c
echo x - netinet/in.h
sed 's/^X//' >netinet/in.h << 'END-of-netinet/in.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)in.h 7.5 (Berkeley) 2/22/88
X */
X
X/*
X * Constants and structures defined by the internet system,
X * Per RFC 790, September 1981.
X */
X
X/*
X * Protocols
X */
X#define IPPROTO_IP 0 /* dummy for IP */
X#define IPPROTO_ICMP 1 /* control message protocol */
X#define IPPROTO_GGP 3 /* gateway^2 (deprecated) */
X#define IPPROTO_TCP 6 /* tcp */
X#define IPPROTO_EGP 8 /* exterior gateway protocol */
X#define IPPROTO_PUP 12 /* pup */
X#define IPPROTO_UDP 17 /* user datagram protocol */
X#define IPPROTO_IDP 22 /* xns idp */
X
X#define IPPROTO_RAW 255 /* raw IP packet */
X#define IPPROTO_MAX 256
X
X
X/*
X * Ports < IPPORT_RESERVED are reserved for
X * privileged processes (e.g. root).
X * Ports > IPPORT_USERRESERVED are reserved
X * for servers, not necessarily privileged.
X */
X#define IPPORT_RESERVED 1024
X#define IPPORT_USERRESERVED 5000
X
X/*
X * Link numbers
X */
X#define IMPLINK_IP 155
X#define IMPLINK_LOWEXPER 156
X#define IMPLINK_HIGHEXPER 158
X
X/*
X * Internet address (a structure for historical reasons)
X */
Xstruct in_addr {
X u_long s_addr;
X};
X
X/*
X * Definitions of bits in internet address integers.
X * On subnets, the decomposition of addresses to host and net parts
X * is done according to subnet mask, not the masks here.
X */
X#define IN_CLASSA(i) (((long)(i) & 0x80000000) == 0)
X#define IN_CLASSA_NET 0xff000000
X#define IN_CLASSA_NSHIFT 24
X#define IN_CLASSA_HOST 0x00ffffff
X#define IN_CLASSA_MAX 128
X
X#define IN_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
X#define IN_CLASSB_NET 0xffff0000
X#define IN_CLASSB_NSHIFT 16
X#define IN_CLASSB_HOST 0x0000ffff
X#define IN_CLASSB_MAX 65536
X
X#define IN_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
X#define IN_CLASSC_NET 0xffffff00
X#define IN_CLASSC_NSHIFT 8
X#define IN_CLASSC_HOST 0x000000ff
X
X#define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
X#define IN_MULTICAST(i) IN_CLASSD(i)
X
X#define IN_EXPERIMENTAL(i) (((long)(i) & 0xe0000000) == 0xe0000000)
X#define IN_BADCLASS(i) (((long)(i) & 0xf0000000) == 0xf0000000)
X
X#define INADDR_ANY (u_long)0x00000000
X#define INADDR_BROADCAST (u_long)0xffffffff /* must be masked */
X#ifndef KERNEL
X#define INADDR_NONE 0xffffffff /* -1 return */
X#endif
X
X#define IN_LOOPBACKNET 127 /* official! */
X
X/*
X * Socket address, internet style.
X */
Xstruct sockaddr_in {
X short sin_family;
X u_short sin_port;
X struct in_addr sin_addr;
X char sin_zero[8];
X};
X
X/*
X * Options for use with [gs]etsockopt at the IP level.
X */
X#define IP_OPTIONS 1 /* set/get IP per-packet options */
X
X#ifdef KERNEL
Xextern struct domain inetdomain;
Xextern struct protosw inetsw[];
Xstruct in_addr in_makeaddr();
Xu_long in_netof(), in_lnaof();
X#endif
END-of-netinet/in.h
echo x - netinet/in_cksum.c
sed 's/^X//' >netinet/in_cksum.c << 'END-of-netinet/in_cksum.c'
X/*
X * Copyright (c) 1988 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)in_cksum.c 7.1 (Berkeley) 3/29/88
X */
X
X#include "../h/types.h"
X#include "../h/mbuf.h"
X
X/*
X * Checksum routine for Internet Protocol family headers (Portable Version).
X *
X * This routine is very heavily used in the network
X * code and should be modified for each CPU to be as fast as possible.
X */
X
X#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
X#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
X
Xin_cksum_c(m, len)
X register struct mbuf *m;
X register int len;
X{
X register u_short *w;
X register int sum = 0;
X register int mlen = 0;
X int byte_swapped = 0;
X
X union {
X char c[2];
X u_short s;
X } s_util;
X union {
X u_short s[2];
X long l;
X } l_util;
X
X for (;m && len; m = m->m_next) {
X if (m->m_len == 0)
X continue;
X w = mtod(m, u_short *);
X if (mlen == -1) {
X /*
X * The first byte of this mbuf is the continuation
X * of a word spanning between this mbuf and the
X * last mbuf.
X *
X * s_util.c[0] is already saved when scanning previous
X * mbuf.
X */
X s_util.c[1] = *(char *)w;
X sum += s_util.s;
X w = (u_short *)((char *)w + 1);
X mlen = m->m_len - 1;
X len--;
X } else
X mlen = m->m_len;
X if (len < mlen)
X mlen = len;
X len -= mlen;
X /*
X * Force to even boundary.
X */
X if ((1 & (int) w) && (mlen > 0)) {
X REDUCE;
X sum <<= 8;
X s_util.c[0] = *(u_char *)w;
X w = (u_short *)((char *)w + 1);
X mlen--;
X byte_swapped = 1;
X }
X /*
X * Unroll the loop to make overhead from
X * branches &c small.
X */
X while ((mlen -= 32) >= 0) {
X sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
X sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7];
X sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11];
X sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15];
X w += 16;
X }
X mlen += 32;
X while ((mlen -= 8) >= 0) {
X sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3];
X w += 4;
X }
X mlen += 8;
X if (mlen == 0 && byte_swapped == 0)
X continue;
X REDUCE;
X while ((mlen -= 2) >= 0) {
X sum += *w++;
X }
X if (byte_swapped) {
X REDUCE;
X sum <<= 8;
X byte_swapped = 0;
X if (mlen == -1) {
X s_util.c[1] = *(char *)w;
X sum += s_util.s;
X mlen = 0;
X } else
X mlen = -1;
X } else if (mlen == -1)
X s_util.c[0] = *(char *)w;
X }
X if (len)
X printf("cksum: out of data\n");
X if (mlen == -1) {
X /* The last mbuf has odd # of bytes. Follow the
X standard (the odd byte may be shifted left by 8 bits
X or not as determined by endian-ness of the machine) */
X s_util.c[1] = 0;
X sum += s_util.s;
X }
X REDUCE;
X return (~sum & 0xffff);
X}
END-of-netinet/in_cksum.c
echo x - netinet/in_pcb.c
sed 's/^X//' >netinet/in_pcb.c << 'END-of-netinet/in_pcb.c'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)in_pcb.c 7.6 (Berkeley) 12/7/87
X */
X
X#include "param.h"
X#include "systm.h"
X#include "dir.h"
X#include "user.h"
X#include "mbuf.h"
X#include "socket.h"
X#include "socketvar.h"
X#include "ioctl.h"
X#include "in.h"
X#include "in_systm.h"
X#include "../net/if.h"
X#include "../net/route.h"
X#include "in_pcb.h"
X#include "in_var.h"
X#include "protosw.h"
X
Xstruct in_addr zeroin_addr;
X
Xin_pcballoc(so, head)
X struct socket *so;
X struct inpcb *head;
X{
X struct mbuf *m;
X register struct inpcb *inp;
X
X m = m_getclr(M_DONTWAIT, MT_PCB);
X if (m == NULL)
X return (ENOBUFS);
X inp = mtod(m, struct inpcb *);
X inp->inp_head = head;
X inp->inp_socket = so;
X insque(inp, head);
X so->so_pcb = (caddr_t)inp;
X return (0);
X}
X
Xin_pcbbind(inp, nam)
X register struct inpcb *inp;
X struct mbuf *nam;
X{
X register struct socket *so = inp->inp_socket;
X register struct inpcb *head = inp->inp_head;
X register struct sockaddr_in *sin;
X u_short lport = 0;
X
X if (in_ifaddr == 0)
X return (EADDRNOTAVAIL);
X if (inp->inp_lport || inp->inp_laddr.s_addr != INADDR_ANY)
X return (EINVAL);
X if (nam == 0)
X goto noname;
X sin = mtod(nam, struct sockaddr_in *);
X if (nam->m_len != sizeof (*sin))
X return (EINVAL);
X if (sin->sin_addr.s_addr != INADDR_ANY) {
X int tport = sin->sin_port;
X
X sin->sin_port = 0; /* yech... */
X if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
X return (EADDRNOTAVAIL);
X sin->sin_port = tport;
X }
X lport = sin->sin_port;
X if (lport) {
X u_short aport = ntohs(lport);
X int wild = 0;
X
X /* GROSS */
X if (aport < IPPORT_RESERVED && u.u_uid != 0)
X return (EACCES);
X /* even GROSSER, but this is the Internet */
X if ((so->so_options & SO_REUSEADDR) == 0 &&
X ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
X (so->so_options & SO_ACCEPTCONN) == 0))
X wild = INPLOOKUP_WILDCARD;
X if (in_pcblookup(head,
X zeroin_addr, 0, sin->sin_addr, lport, wild))
X return (EADDRINUSE);
X }
X inp->inp_laddr = sin->sin_addr;
Xnoname:
X if (lport == 0)
X do {
X if (head->inp_lport++ < IPPORT_RESERVED ||
X head->inp_lport > IPPORT_USERRESERVED)
X head->inp_lport = IPPORT_RESERVED;
X lport = htons(head->inp_lport);
X } while (in_pcblookup(head,
X zeroin_addr, 0, inp->inp_laddr, lport, 0));
X inp->inp_lport = lport;
X return (0);
X}
X
X/*
X * Connect from a socket to a specified address.
X * Both address and port must be specified in argument sin.
X * If don't have a local address for this socket yet,
X * then pick one.
X */
Xin_pcbconnect(inp, nam)
X register struct inpcb *inp;
X struct mbuf *nam;
X{
X struct in_ifaddr *ia;
X struct sockaddr_in *ifaddr;
X register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
X
X if (nam->m_len != sizeof (*sin))
X return (EINVAL);
X if (sin->sin_family != AF_INET)
X return (EAFNOSUPPORT);
X if (sin->sin_port == 0)
X return (EADDRNOTAVAIL);
X if (in_ifaddr) {
X /*
X * If the destination address is INADDR_ANY,
X * use the primary local address.
X * If the supplied address is INADDR_BROADCAST,
X * and the primary interface supports broadcast,
X * choose the broadcast address for that interface.
X */
X#define satosin(sa) ((struct sockaddr_in *)(sa))
X if (sin->sin_addr.s_addr == INADDR_ANY)
X sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
X else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
X (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
X sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
X }
X if (inp->inp_laddr.s_addr == INADDR_ANY) {
X register struct route *ro;
X struct ifnet *ifp;
X
X ia = (struct in_ifaddr *)0;
X /*
X * If route is known or can be allocated now,
X * our src addr is taken from the i/f, else punt.
X */
X ro = &inp->inp_route;
X if (ro->ro_rt &&
X (satosin(&ro->ro_dst)->sin_addr.s_addr !=
X sin->sin_addr.s_addr ||
X inp->inp_socket->so_options & SO_DONTROUTE)) {
X RTFREE(ro->ro_rt);
X ro->ro_rt = (struct rtentry *)0;
X }
X if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
X (ro->ro_rt == (struct rtentry *)0 ||
X ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
X /* No route yet, so try to acquire one */
X ro->ro_dst.sa_family = AF_INET;
X ((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
X sin->sin_addr;
X rtalloc(ro);
X }
X /*
X * If we found a route, use the address
X * corresponding to the outgoing interface
X * unless it is the loopback (in case a route
X * to our address on another net goes to loopback).
X */
X if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp) &&
X (ifp->if_flags & IFF_LOOPBACK) == 0)
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if (ia->ia_ifp == ifp)
X break;
X if (ia == 0) {
X int fport = sin->sin_port;
X
X sin->sin_port = 0;
X ia = (struct in_ifaddr *)
X ifa_ifwithdstaddr((struct sockaddr *)sin);
X sin->sin_port = fport;
X if (ia == 0)
X ia = in_iaonnetof(in_netof(sin->sin_addr));
X if (ia == 0)
X ia = in_ifaddr;
X if (ia == 0)
X return (EADDRNOTAVAIL);
X }
X ifaddr = (struct sockaddr_in *)&ia->ia_addr;
X }
X if (in_pcblookup(inp->inp_head,
X sin->sin_addr,
X sin->sin_port,
X inp->inp_laddr.s_addr ? inp->inp_laddr : ifaddr->sin_addr,
X inp->inp_lport,
X 0))
X return (EADDRINUSE);
X if (inp->inp_laddr.s_addr == INADDR_ANY) {
X if (inp->inp_lport == 0)
X (void)in_pcbbind(inp, (struct mbuf *)0);
X inp->inp_laddr = ifaddr->sin_addr;
X }
X inp->inp_faddr = sin->sin_addr;
X inp->inp_fport = sin->sin_port;
X return (0);
X}
X
Xin_pcbdisconnect(inp)
X struct inpcb *inp;
X{
X
X inp->inp_faddr.s_addr = INADDR_ANY;
X inp->inp_fport = 0;
X if (inp->inp_socket->so_state & SS_NOFDREF)
X in_pcbdetach(inp);
X}
X
Xin_pcbdetach(inp)
X struct inpcb *inp;
X{
X struct socket *so = inp->inp_socket;
X
X so->so_pcb = 0;
X sofree(so);
X if (inp->inp_options)
X (void)m_free(inp->inp_options);
X if (inp->inp_route.ro_rt)
X rtfree(inp->inp_route.ro_rt);
X remque(inp);
X (void) m_free(dtom(inp));
X}
X
Xin_setsockaddr(inp, nam)
X register struct inpcb *inp;
X struct mbuf *nam;
X{
X register struct sockaddr_in *sin;
X
X nam->m_len = sizeof (*sin);
X sin = mtod(nam, struct sockaddr_in *);
X bzero((caddr_t)sin, sizeof (*sin));
X sin->sin_family = AF_INET;
X sin->sin_port = inp->inp_lport;
X sin->sin_addr = inp->inp_laddr;
X}
X
Xin_setpeeraddr(inp, nam)
X struct inpcb *inp;
X struct mbuf *nam;
X{
X register struct sockaddr_in *sin;
X
X nam->m_len = sizeof (*sin);
X sin = mtod(nam, struct sockaddr_in *);
X bzero((caddr_t)sin, sizeof (*sin));
X sin->sin_family = AF_INET;
X sin->sin_port = inp->inp_fport;
X sin->sin_addr = inp->inp_faddr;
X}
X
X/*
X * Pass some notification to all connections of a protocol
X * associated with address dst. Call the protocol specific
X * routine (if any) to handle each connection.
X */
Xin_pcbnotify(head, dst, errno, notify)
X struct inpcb *head;
X register struct in_addr *dst;
X int errno, (*notify)();
X{
X register struct inpcb *inp, *oinp;
X int s = splimp();
X
X for (inp = head->inp_next; inp != head;) {
X if (inp->inp_faddr.s_addr != dst->s_addr ||
X inp->inp_socket == 0) {
X inp = inp->inp_next;
X continue;
X }
X if (errno)
X inp->inp_socket->so_error = errno;
X oinp = inp;
X inp = inp->inp_next;
X if (notify)
X (*notify)(oinp);
X }
X splx(s);
X}
X
X/*
X * Check for alternatives when higher level complains
X * about service problems. For now, invalidate cached
X * routing information. If the route was created dynamically
X * (by a redirect), time to try a default gateway again.
X */
Xin_losing(inp)
X struct inpcb *inp;
X{
X register struct rtentry *rt;
X
X if ((rt = inp->inp_route.ro_rt)) {
X if (rt->rt_flags & RTF_DYNAMIC)
X (void) rtrequest((int)SIOCDELRT, rt);
X rtfree(rt);
X inp->inp_route.ro_rt = 0;
X /*
X * A new route can be allocated
X * the next time output is attempted.
X */
X }
X}
X
X/*
X * After a routing change, flush old routing
X * and allocate a (hopefully) better one.
X */
Xin_rtchange(inp)
X register struct inpcb *inp;
X{
X if (inp->inp_route.ro_rt) {
X rtfree(inp->inp_route.ro_rt);
X inp->inp_route.ro_rt = 0;
X /*
X * A new route can be allocated the next time
X * output is attempted.
X */
X }
X}
X
Xstruct inpcb *
Xin_pcblookup(head, faddr, fport, laddr, lport, flags)
X struct inpcb *head;
X struct in_addr faddr, laddr;
X u_short fport, lport;
X int flags;
X{
X register struct inpcb *inp, *match = 0;
X int matchwild = 3, wildcard;
X
X for (inp = head->inp_next; inp != head; inp = inp->inp_next) {
X if (inp->inp_lport != lport)
X continue;
X wildcard = 0;
X if (inp->inp_laddr.s_addr != INADDR_ANY) {
X if (laddr.s_addr == INADDR_ANY)
X wildcard++;
X else if (inp->inp_laddr.s_addr != laddr.s_addr)
X continue;
X } else {
X if (laddr.s_addr != INADDR_ANY)
X wildcard++;
X }
X if (inp->inp_faddr.s_addr != INADDR_ANY) {
X if (faddr.s_addr == INADDR_ANY)
X wildcard++;
X else if (inp->inp_faddr.s_addr != faddr.s_addr ||
X inp->inp_fport != fport)
X continue;
X } else {
X if (faddr.s_addr != INADDR_ANY)
X wildcard++;
X }
X if (wildcard && (flags & INPLOOKUP_WILDCARD) == 0)
X continue;
X if (wildcard < matchwild) {
X match = inp;
X matchwild = wildcard;
X if (matchwild == 0)
X break;
X }
X }
X return (match);
X}
END-of-netinet/in_pcb.c
echo x - netinet/in_pcb.h
sed 's/^X//' >netinet/in_pcb.h << 'END-of-netinet/in_pcb.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)in_pcb.h 7.2 (Berkeley) 12/7/87
X */
X
X/*
X * Common structure pcb for internet protocol implementation.
X * Here are stored pointers to local and foreign host table
X * entries, local and foreign socket numbers, and pointers
X * up (to a socket structure) and down (to a protocol-specific)
X * control block.
X */
Xstruct inpcb {
X struct inpcb *inp_next,*inp_prev;
X /* pointers to other pcb's */
X struct inpcb *inp_head; /* pointer back to chain of inpcb's
X for this protocol */
X struct in_addr inp_faddr; /* foreign host table entry */
X u_short inp_fport; /* foreign port */
X struct in_addr inp_laddr; /* local host table entry */
X u_short inp_lport; /* local port */
X struct socket *inp_socket; /* back pointer to socket */
X caddr_t inp_ppcb; /* pointer to per-protocol pcb */
X struct route inp_route; /* placeholder for routing entry */
X struct mbuf *inp_options; /* IP options */
X};
X
X#define INPLOOKUP_WILDCARD 1
X#define INPLOOKUP_SETLOCAL 2
X
X#define sotoinpcb(so) ((struct inpcb *)(so)->so_pcb)
X
X#ifdef KERNEL
Xstruct inpcb *in_pcblookup();
X#endif
END-of-netinet/in_pcb.h
echo x - netinet/in_proto.c
sed 's/^X//' >netinet/in_proto.c << 'END-of-netinet/in_proto.c'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)in_proto.c 7.2 (Berkeley) 12/7/87
X */
X
X#include "param.h"
X#include "socket.h"
X#include "protosw.h"
X#include "domain.h"
X#include "mbuf.h"
X
X#include "in.h"
X#include "in_systm.h"
X
X/*
X * TCP/IP protocol family: IP, ICMP, UDP, TCP.
X */
Xint ip_output(),ip_ctloutput();
Xint ip_init(),ip_slowtimo(),ip_drain();
Xint icmp_input();
Xint udp_input(),udp_ctlinput();
Xint udp_usrreq();
Xint udp_init();
Xint tcp_input(),tcp_ctlinput();
Xint tcp_usrreq(),tcp_ctloutput();
Xint tcp_init(),tcp_fasttimo(),tcp_slowtimo(),tcp_drain();
Xint rip_input(),rip_output(),rip_ctloutput();
Xextern int raw_usrreq();
X/*
X * IMP protocol family: raw interface.
X * Using the raw interface entry to get the timer routine
X * in is a kludge.
X */
X#include "imp.h"
X#if NIMP > 0
Xint rimp_output(), hostslowtimo();
X#endif
X
X#ifdef NSIP
Xint idpip_input(), nsip_ctlinput();
X#endif
X
Xextern struct domain inetdomain;
X
Xstruct protosw inetsw[] = {
X{ 0, &inetdomain, 0, 0,
X 0, ip_output, 0, 0,
X 0,
X ip_init, 0, ip_slowtimo, ip_drain,
X},
X{ SOCK_DGRAM, &inetdomain, IPPROTO_UDP, PR_ATOMIC|PR_ADDR,
X udp_input, 0, udp_ctlinput, ip_ctloutput,
X udp_usrreq,
X udp_init, 0, 0, 0,
X},
X{ SOCK_STREAM, &inetdomain, IPPROTO_TCP, PR_CONNREQUIRED|PR_WANTRCVD,
X tcp_input, 0, tcp_ctlinput, tcp_ctloutput,
X tcp_usrreq,
X tcp_init, tcp_fasttimo, tcp_slowtimo, tcp_drain,
X},
X{ SOCK_RAW, &inetdomain, IPPROTO_RAW, PR_ATOMIC|PR_ADDR,
X rip_input, rip_output, 0, rip_ctloutput,
X raw_usrreq,
X 0, 0, 0, 0,
X},
X{ SOCK_RAW, &inetdomain, IPPROTO_ICMP, PR_ATOMIC|PR_ADDR,
X icmp_input, rip_output, 0, rip_ctloutput,
X raw_usrreq,
X 0, 0, 0, 0,
X},
X#ifdef NSIP
X{ SOCK_RAW, &inetdomain, IPPROTO_IDP, PR_ATOMIC|PR_ADDR,
X idpip_input, rip_output, nsip_ctlinput, 0,
X raw_usrreq,
X 0, 0, 0, 0,
X},
X#endif
X /* raw wildcard */
X{ SOCK_RAW, &inetdomain, 0, PR_ATOMIC|PR_ADDR,
X rip_input, rip_output, 0, rip_ctloutput,
X raw_usrreq,
X 0, 0, 0, 0,
X},
X};
X
Xstruct domain inetdomain =
X { AF_INET, "internet", 0, 0, 0,
X inetsw, &inetsw[sizeof(inetsw)/sizeof(inetsw[0])] };
X
X#if NIMP > 0
Xextern struct domain impdomain;
X
Xstruct protosw impsw[] = {
X{ SOCK_RAW, &impdomain, 0, PR_ATOMIC|PR_ADDR,
X 0, rimp_output, 0, 0,
X raw_usrreq,
X 0, 0, hostslowtimo, 0,
X},
X};
X
Xstruct domain impdomain =
X { AF_IMPLINK, "imp", 0, 0, 0,
X impsw, &impsw[sizeof (impsw)/sizeof(impsw[0])] };
X#endif
X
X#include "hy.h"
X#if NHY > 0
X/*
X * HYPERchannel protocol family: raw interface.
X */
Xint rhy_output();
Xextern struct domain hydomain;
X
Xstruct protosw hysw[] = {
X{ SOCK_RAW, &hydomain, 0, PR_ATOMIC|PR_ADDR,
X 0, rhy_output, 0, 0,
X raw_usrreq,
X 0, 0, 0, 0,
X},
X};
X
Xstruct domain hydomain =
X { AF_HYLINK, "hy", 0, 0, 0, hysw, &hysw[sizeof (hysw)/sizeof(hysw[0])] };
X#endif
END-of-netinet/in_proto.c
echo x - netinet/in_systm.h
sed 's/^X//' >netinet/in_systm.h << 'END-of-netinet/in_systm.h'
X/*
X * Copyright (c) 1982, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)in_systm.h 7.2 (Berkeley) 12/7/87
X */
X
X/*
X * Miscellaneous internetwork
X * definitions for kernel.
X */
X
X/*
X * Network types.
X *
X * Internally the system keeps counters in the headers with the bytes
X * swapped so that VAX instructions will work on them. It reverses
X * the bytes before transmission at each protocol level. The n_ types
X * represent the types with the bytes in ``high-ender'' order.
X */
Xtypedef u_short n_short; /* short as received from the net */
Xtypedef u_long n_long; /* long as received from the net */
X
Xtypedef u_long n_time; /* ms since 00:00 GMT, byte rev */
X
X#ifdef KERNEL
Xn_time iptime();
X#endif
END-of-netinet/in_systm.h
echo x - netinet/in_var.h
sed 's/^X//' >netinet/in_var.h << 'END-of-netinet/in_var.h'
X/*
X * Copyright (c) 1985, 1986 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that this notice is preserved and that due credit is given
X * to the University of California at Berkeley. The name of the University
X * may not be used to endorse or promote products derived from this
X * software without specific prior written permission. This software
X * is provided ``as is'' without express or implied warranty.
X *
X * @(#)in_var.h 7.2 (Berkeley) 12/7/87
X */
X
X/*
X * Interface address, Internet version. One of these structures
X * is allocated for each interface with an Internet address.
X * The ifaddr structure contains the protocol-independent part
X * of the structure and is assumed to be first.
X */
Xstruct in_ifaddr {
X struct ifaddr ia_ifa; /* protocol-independent info */
X#define ia_addr ia_ifa.ifa_addr
X#define ia_broadaddr ia_ifa.ifa_broadaddr
X#define ia_dstaddr ia_ifa.ifa_dstaddr
X#define ia_ifp ia_ifa.ifa_ifp
X u_long ia_net; /* network number of interface */
X u_long ia_netmask; /* mask of net part */
X u_long ia_subnet; /* subnet number, including net */
X u_long ia_subnetmask; /* mask of net + subnet */
X struct in_addr ia_netbroadcast; /* broadcast addr for (logical) net */
X int ia_flags;
X struct in_ifaddr *ia_next; /* next in list of internet addresses */
X};
X/*
X * Given a pointer to an in_ifaddr (ifaddr),
X * return a pointer to the addr as a sockadd_in.
X */
X#define IA_SIN(ia) ((struct sockaddr_in *)(&((struct in_ifaddr *)ia)->ia_addr))
X/*
X * ia_flags
X */
X#define IFA_ROUTE 0x01 /* routing entry installed */
X
X#ifdef KERNEL
Xstruct in_ifaddr *in_ifaddr;
Xstruct in_ifaddr *in_iaonnetof();
Xstruct ifqueue ipintrq; /* ip packet input queue */
X#endif
END-of-netinet/in_var.h
exit
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads