V1.51 ((netns 1 of 2) updated IP/TCP and XNS sources for 4.3BSD)
Keith Bostic
bostic at OKEEFFE.BERKELEY.EDU
Tue Apr 5 13:18:16 AEST 1988
Subject: (netns 1 of 2) updated IP/TCP and XNS sources for 4.3BSD
Index: sys 4.3BSD
Description:
This is number 6 of 11 total articles posted to the newsgroup
comp.bugs.4bsd.ucb-fixes. This archive is number 1 of the 2
articles that make up the netns 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:
#
# netns
# netns/idp.h
# netns/idp_usrreq.c
# netns/idp_var.h
# netns/ns.c
# netns/ns.h
# netns/ns_error.c
# netns/ns_error.h
# netns/ns_if.h
# netns/ns_input.c
# netns/ns_ip.c
# netns/ns_output.c
# netns/ns_pcb.c
# netns/ns_pcb.h
# netns/ns_proto.c
#
echo c - netns
mkdir netns > /dev/null 2>&1
echo x - netns/idp.h
sed 's/^X//' >netns/idp.h << 'END-of-netns/idp.h'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)idp.h 7.2 (Berkeley) 1/20/88
X */
X
X/*
X * Definitions for NS(tm) Internet Datagram Protocol
X */
Xstruct idp {
X u_short idp_sum; /* Checksum */
X u_short idp_len; /* Length, in bytes, including header */
X u_char idp_tc; /* Transport Crontrol (i.e. hop count) */
X u_char idp_pt; /* Packet Type (i.e. level 2 protocol) */
X struct ns_addr idp_dna; /* Destination Network Address */
X struct ns_addr idp_sna; /* Source Network Address */
X};
END-of-netns/idp.h
echo x - netns/idp_usrreq.c
sed 's/^X//' >netns/idp_usrreq.c << 'END-of-netns/idp_usrreq.c'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)idp_usrreq.c 7.2 (Berkeley) 1/20/88
X */
X
X#include "param.h"
X#include "dir.h"
X#include "user.h"
X#include "mbuf.h"
X#include "protosw.h"
X#include "socket.h"
X#include "socketvar.h"
X#include "errno.h"
X#include "stat.h"
X
X#include "../net/if.h"
X#include "../net/route.h"
X
X#include "ns.h"
X#include "ns_pcb.h"
X#include "ns_if.h"
X#include "idp.h"
X#include "idp_var.h"
X#include "ns_error.h"
X
X/*
X * IDP protocol implementation.
X */
X
Xstruct sockaddr_ns idp_ns = { AF_NS };
X
X/*
X * This may also be called for raw listeners.
X */
Xidp_input(m, nsp, ifp)
X struct mbuf *m;
X register struct nspcb *nsp;
X struct ifnet *ifp;
X{
X register struct idp *idp = mtod(m, struct idp *);
X
X if (nsp==0)
X panic("No nspcb");
X /*
X * Construct sockaddr format source address.
X * Stuff source address and datagram in user buffer.
X */
X idp_ns.sns_addr = idp->idp_sna;
X if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) {
X register struct ifaddr *ia;
X
X for (ia = ifp->if_addrlist; ia; ia = ia->ifa_next) {
X if (ia->ifa_addr.sa_family == AF_NS) {
X idp_ns.sns_addr.x_net =
X IA_SNS(ia)->sns_addr.x_net;
X break;
X }
X }
X }
X nsp->nsp_rpt = idp->idp_pt;
X if ( ! (nsp->nsp_flags & NSP_RAWIN) ) {
X m->m_len -= sizeof (struct idp);
X m->m_off += sizeof (struct idp);
X }
X if (sbappendaddr(&nsp->nsp_socket->so_rcv, (struct sockaddr *)&idp_ns,
X m, (struct mbuf *)0) == 0)
X goto bad;
X sorwakeup(nsp->nsp_socket);
X return;
Xbad:
X m_freem(m);
X}
X
Xidp_abort(nsp)
X struct nspcb *nsp;
X{
X struct socket *so = nsp->nsp_socket;
X
X ns_pcbdisconnect(nsp);
X soisdisconnected(so);
X}
X/*
X * Drop connection, reporting
X * the specified error.
X */
Xstruct nspcb *
Xidp_drop(nsp, errno)
X register struct nspcb *nsp;
X int errno;
X{
X struct socket *so = nsp->nsp_socket;
X
X /*
X * someday, in the xerox world
X * we will generate error protocol packets
X * announcing that the socket has gone away.
X */
X /*if (TCPS_HAVERCVDSYN(tp->t_state)) {
X tp->t_state = TCPS_CLOSED;
X (void) tcp_output(tp);
X }*/
X so->so_error = errno;
X ns_pcbdisconnect(nsp);
X soisdisconnected(so);
X}
X
Xint noIdpRoute;
Xidp_output(nsp, m0)
X struct nspcb *nsp;
X struct mbuf *m0;
X{
X register struct mbuf *m;
X register struct idp *idp;
X register struct socket *so;
X register int len = 0;
X register struct route *ro;
X struct mbuf *mprev;
X extern int idpcksum;
X
X /*
X * Calculate data length.
X */
X for (m = m0; m; m = m->m_next) {
X mprev = m;
X len += m->m_len;
X }
X /*
X * Make sure packet is actually of even length.
X */
X
X if (len & 1) {
X m = mprev;
X if (m->m_len + m->m_off < MMAXOFF) {
X m->m_len++;
X } else {
X struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
X
X if (m1 == 0) {
X m_freem(m0);
X return (ENOBUFS);
X }
X m1->m_len = 1;
X m1->m_off = MMAXOFF - 1;
X * mtod(m1, char *) = 0;
X m->m_next = m1;
X }
X }
X
X /*
X * Fill in mbuf with extended IDP header
X * and addresses and length put into network format.
X */
X if (nsp->nsp_flags & NSP_RAWOUT) {
X m = m0;
X idp = mtod(m, struct idp *);
X } else {
X m = m_get(M_DONTWAIT, MT_HEADER);
X if (m == 0) {
X m_freem(m0);
X return (ENOBUFS);
X }
X m->m_off = MMAXOFF - sizeof (struct idp) - 2;
X /* adjust to start on longword bdry
X for NSIP on gould */
X m->m_len = sizeof (struct idp);
X m->m_next = m0;
X idp = mtod(m, struct idp *);
X idp->idp_tc = 0;
X idp->idp_pt = nsp->nsp_dpt;
X idp->idp_sna = nsp->nsp_laddr;
X idp->idp_dna = nsp->nsp_faddr;
X len += sizeof (struct idp);
X }
X
X idp->idp_len = htons((u_short)len);
X
X if (idpcksum) {
X idp->idp_sum = 0;
X len = ((len - 1) | 1) + 1;
X idp->idp_sum = ns_cksum(m, len);
X } else
X idp->idp_sum = 0xffff;
X
X /*
X * Output datagram.
X */
X so = nsp->nsp_socket;
X if (so->so_options & SO_DONTROUTE)
X return (ns_output(m, (struct route *)0,
X (so->so_options & SO_BROADCAST) | NS_ROUTETOIF));
X /*
X * Use cached route for previous datagram if
X * possible. If the previous net was the same
X * and the interface was a broadcast medium, or
X * if the previous destination was identical,
X * then we are ok.
X *
X * NB: We don't handle broadcasts because that
X * would require 3 subroutine calls.
X */
X ro = &nsp->nsp_route;
X#ifdef ancient_history
X /*
X * I think that this will all be handled in ns_pcbconnect!
X */
X if (ro->ro_rt) {
X if(ns_neteq(nsp->nsp_lastdst, idp->idp_dna)) {
X /*
X * This assumes we have no GH type routes
X */
X if (ro->ro_rt->rt_flags & RTF_HOST) {
X if (!ns_hosteq(nsp->nsp_lastdst, idp->idp_dna))
X goto re_route;
X
X }
X if ((ro->ro_rt->rt_flags & RTF_GATEWAY) == 0) {
X register struct ns_addr *dst =
X &satons_addr(ro->ro_dst);
X dst->x_host = idp->idp_dna.x_host;
X }
X /*
X * Otherwise, we go through the same gateway
X * and dst is already set up.
X */
X } else {
X re_route:
X RTFREE(ro->ro_rt);
X ro->ro_rt = (struct rtentry *)0;
X }
X }
X nsp->nsp_lastdst = idp->idp_dna;
X#endif ancient_history
X if (noIdpRoute) ro = 0;
X return (ns_output(m, ro, so->so_options & SO_BROADCAST));
X}
X/* ARGSUSED */
Xidp_ctloutput(req, so, level, name, value)
X int req, level;
X struct socket *so;
X int name;
X struct mbuf **value;
X{
X register struct mbuf *m;
X struct nspcb *nsp = sotonspcb(so);
X int mask, error = 0;
X extern long ns_pexseq;
X
X if (nsp == NULL)
X return (EINVAL);
X
X switch (req) {
X
X case PRCO_GETOPT:
X if (value==NULL)
X return (EINVAL);
X m = m_get(M_DONTWAIT, MT_DATA);
X if (m==NULL)
X return (ENOBUFS);
X switch (name) {
X
X case SO_ALL_PACKETS:
X mask = NSP_ALL_PACKETS;
X goto get_flags;
X
X case SO_HEADERS_ON_INPUT:
X mask = NSP_RAWIN;
X goto get_flags;
X
X case SO_HEADERS_ON_OUTPUT:
X mask = NSP_RAWOUT;
X get_flags:
X m->m_len = sizeof(short);
X m->m_off = MMAXOFF - sizeof(short);
X *mtod(m, short *) = nsp->nsp_flags & mask;
X break;
X
X case SO_DEFAULT_HEADERS:
X m->m_len = sizeof(struct idp);
X m->m_off = MMAXOFF - sizeof(struct idp);
X {
X register struct idp *idp = mtod(m, struct idp *);
X idp->idp_len = 0;
X idp->idp_sum = 0;
X idp->idp_tc = 0;
X idp->idp_pt = nsp->nsp_dpt;
X idp->idp_dna = nsp->nsp_faddr;
X idp->idp_sna = nsp->nsp_laddr;
X }
X break;
X
X case SO_SEQNO:
X m->m_len = sizeof(long);
X m->m_off = MMAXOFF - sizeof(long);
X *mtod(m, long *) = ns_pexseq++;
X break;
X
X default:
X error = EINVAL;
X }
X *value = m;
X break;
X
X case PRCO_SETOPT:
X switch (name) {
X int *ok;
X
X case SO_ALL_PACKETS:
X mask = NSP_ALL_PACKETS;
X goto set_head;
X
X case SO_HEADERS_ON_INPUT:
X mask = NSP_RAWIN;
X goto set_head;
X
X case SO_HEADERS_ON_OUTPUT:
X mask = NSP_RAWOUT;
X set_head:
X if (value && *value) {
X ok = mtod(*value, int *);
X if (*ok)
X nsp->nsp_flags |= mask;
X else
X nsp->nsp_flags &= ~mask;
X } else error = EINVAL;
X break;
X
X case SO_DEFAULT_HEADERS:
X {
X register struct idp *idp
X = mtod(*value, struct idp *);
X nsp->nsp_dpt = idp->idp_pt;
X }
X break;
X#ifdef NSIP
X
X case SO_NSIP_ROUTE:
X error = nsip_route(*value);
X break;
X#endif NSIP
X default:
X error = EINVAL;
X }
X if (value && *value)
X m_freem(*value);
X break;
X }
X return (error);
X}
X
X/*ARGSUSED*/
Xidp_usrreq(so, req, m, nam, rights)
X struct socket *so;
X int req;
X struct mbuf *m, *nam, *rights;
X{
X struct nspcb *nsp = sotonspcb(so);
X int error = 0;
X
X if (req == PRU_CONTROL)
X return (ns_control(so, (int)m, (caddr_t)nam,
X (struct ifnet *)rights));
X if (rights && rights->m_len) {
X error = EINVAL;
X goto release;
X }
X if (nsp == NULL && req != PRU_ATTACH) {
X error = EINVAL;
X goto release;
X }
X switch (req) {
X
X case PRU_ATTACH:
X if (nsp != NULL) {
X error = EINVAL;
X break;
X }
X error = ns_pcballoc(so, &nspcb);
X if (error)
X break;
X error = soreserve(so, 2048, 2048);
X if (error)
X break;
X break;
X
X case PRU_DETACH:
X if (nsp == NULL) {
X error = ENOTCONN;
X break;
X }
X ns_pcbdetach(nsp);
X break;
X
X case PRU_BIND:
X error = ns_pcbbind(nsp, nam);
X break;
X
X case PRU_LISTEN:
X error = EOPNOTSUPP;
X break;
X
X case PRU_CONNECT:
X if (!ns_nullhost(nsp->nsp_faddr)) {
X error = EISCONN;
X break;
X }
X error = ns_pcbconnect(nsp, nam);
X if (error == 0)
X soisconnected(so);
X break;
X
X case PRU_CONNECT2:
X error = EOPNOTSUPP;
X break;
X
X case PRU_ACCEPT:
X error = EOPNOTSUPP;
X break;
X
X case PRU_DISCONNECT:
X if (ns_nullhost(nsp->nsp_faddr)) {
X error = ENOTCONN;
X break;
X }
X ns_pcbdisconnect(nsp);
X soisdisconnected(so);
X break;
X
X case PRU_SHUTDOWN:
X socantsendmore(so);
X break;
X
X case PRU_SEND:
X {
X struct ns_addr laddr;
X int s;
X
X if (nam) {
X laddr = nsp->nsp_laddr;
X if (!ns_nullhost(nsp->nsp_faddr)) {
X error = EISCONN;
X break;
X }
X /*
X * Must block input while temporarily connected.
X */
X s = splnet();
X error = ns_pcbconnect(nsp, nam);
X if (error) {
X splx(s);
X break;
X }
X } else {
X if (ns_nullhost(nsp->nsp_faddr)) {
X error = ENOTCONN;
X break;
X }
X }
X error = idp_output(nsp, m);
X m = NULL;
X if (nam) {
X ns_pcbdisconnect(nsp);
X splx(s);
X nsp->nsp_laddr.x_host = laddr.x_host;
X nsp->nsp_laddr.x_port = laddr.x_port;
X }
X }
X break;
X
X case PRU_ABORT:
X ns_pcbdetach(nsp);
X sofree(so);
X soisdisconnected(so);
X break;
X
X case PRU_SOCKADDR:
X ns_setsockaddr(nsp, nam);
X break;
X
X case PRU_PEERADDR:
X ns_setpeeraddr(nsp, nam);
X break;
X
X case PRU_SENSE:
X /*
X * stat: don't bother with a blocksize.
X */
X return (0);
X
X case PRU_SENDOOB:
X case PRU_FASTTIMO:
X case PRU_SLOWTIMO:
X case PRU_PROTORCV:
X case PRU_PROTOSEND:
X error = EOPNOTSUPP;
X break;
X
X case PRU_CONTROL:
X case PRU_RCVD:
X case PRU_RCVOOB:
X return (EOPNOTSUPP); /* do not free mbuf's */
X
X default:
X panic("idp_usrreq");
X }
Xrelease:
X if (m != NULL)
X m_freem(m);
X return (error);
X}
X/*ARGSUSED*/
Xidp_raw_usrreq(so, req, m, nam, rights)
X struct socket *so;
X int req;
X struct mbuf *m, *nam, *rights;
X{
X int error = 0;
X struct nspcb *nsp = sotonspcb(so);
X extern struct nspcb nsrawpcb;
X
X switch (req) {
X
X case PRU_ATTACH:
X
X if (!suser() || (nsp != NULL)) {
X error = EINVAL;
X break;
X }
X error = ns_pcballoc(so, &nsrawpcb);
X if (error)
X break;
X error = soreserve(so, 2048, 2048);
X if (error)
X break;
X nsp = sotonspcb(so);
X nsp->nsp_faddr.x_host = ns_broadhost;
X nsp->nsp_flags = NSP_RAWIN | NSP_RAWOUT;
X break;
X default:
X error = idp_usrreq(so, req, m, nam, rights);
X }
X return (error);
X}
X
END-of-netns/idp_usrreq.c
echo x - netns/idp_var.h
sed 's/^X//' >netns/idp_var.h << 'END-of-netns/idp_var.h'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)idp_var.h 7.2 (Berkeley) 1/20/88
X */
X
X/*
X * IDP Kernel Structures and Variables
X */
Xstruct idpstat {
X int idps_badsum; /* checksum bad */
X int idps_tooshort; /* packet too short */
X int idps_toosmall; /* not enough data */
X int idps_badhlen; /* ip header length < data size */
X int idps_badlen; /* ip length < ip header length */
X};
X
X#ifdef KERNEL
Xstruct idpstat idpstat;
X#endif
END-of-netns/idp_var.h
echo x - netns/ns.c
sed 's/^X//' >netns/ns.c << 'END-of-netns/ns.c'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns.c 7.2 (Berkeley) 1/20/88
X */
X
X#include "param.h"
X#include "mbuf.h"
X#include "ioctl.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
X
X#include "../net/if.h"
X#include "../net/route.h"
X#include "../net/af.h"
X
X#include "ns.h"
X#include "ns_if.h"
X
X#ifdef NS
X
Xstruct ns_ifaddr *ns_ifaddr;
X
Xns_hash(sns, hp)
X register struct sockaddr_ns *sns;
X struct afhash *hp;
X{
X register long hash = 0;
X register u_short *s = sns->sns_addr.x_host.s_host;
X union {
X union ns_net net_e;
X long long_e;
X } net;
X
X net.net_e = sns->sns_addr.x_net;
X hp->afh_nethash = net.long_e;
X hash = *s++; hash <<= 8; hash += *s++; hash <<= 8; hash += *s;
X hp->afh_hosthash = hash;
X}
X
X
Xns_netmatch(sns1, sns2)
X struct sockaddr_ns *sns1, *sns2;
X{
X
X return (ns_neteq(sns1->sns_addr, sns2->sns_addr));
X}
X
X/*
X * Generic internet control operations (ioctl's).
X */
X/* ARGSUSED */
Xns_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 ns_ifaddr *ia;
X struct ifaddr *ifa;
X struct mbuf *m;
X
X /*
X * Find address for this interface, if it exists.
X */
X if (ifp == 0)
X return (EADDRNOTAVAIL);
X for (ia = ns_ifaddr; ia; ia = ia->ia_next)
X if (ia->ia_ifp == ifp)
X break;
X
X switch (cmd) {
X
X case SIOCGIFADDR:
X if (ia == (struct ns_ifaddr *)0)
X return (EADDRNOTAVAIL);
X ifr->ifr_addr = ia->ia_addr;
X return (0);
X
X
X case SIOCGIFBRDADDR:
X if (ia == (struct ns_ifaddr *)0)
X return (EADDRNOTAVAIL);
X if ((ifp->if_flags & IFF_BROADCAST) == 0)
X return (EINVAL);
X ifr->ifr_dstaddr = ia->ia_broadaddr;
X return (0);
X
X case SIOCGIFDSTADDR:
X if (ia == (struct ns_ifaddr *)0)
X return (EADDRNOTAVAIL);
X if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
X return (EINVAL);
X ifr->ifr_dstaddr = ia->ia_dstaddr;
X return (0);
X }
X
X if (!suser())
X return (u.u_error);
X
X switch (cmd) {
X
X case SIOCSIFADDR:
X case SIOCSIFDSTADDR:
X if (ia == (struct ns_ifaddr *)0) {
X m = m_getclr(M_WAIT, MT_IFADDR);
X if (m == (struct mbuf *)NULL)
X return (ENOBUFS);
X if (ia = ns_ifaddr) {
X for ( ; ia->ia_next; ia = ia->ia_next)
X ;
X ia->ia_next = mtod(m, struct ns_ifaddr *);
X } else
X ns_ifaddr = mtod(m, struct ns_ifaddr *);
X ia = mtod(m, struct ns_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_SNS(ia)->sns_family = AF_NS;
X }
X }
X
X switch (cmd) {
X
X case SIOCSIFDSTADDR:
X if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
X return (EINVAL);
X if (ia->ia_flags & IFA_ROUTE) {
X rtinit(&ia->ia_dstaddr, &ia->ia_addr,
X (int)SIOCDELRT, RTF_HOST);
X ia->ia_flags &= ~IFA_ROUTE;
X }
X if (ifp->if_ioctl) {
X int error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia);
X if (error)
X return (error);
X }
X ia->ia_dstaddr = ifr->ifr_dstaddr;
X return (0);
X
X case SIOCSIFADDR:
X return
X (ns_ifinit(ifp, ia, (struct sockaddr_ns *)&ifr->ifr_addr));
X
X default:
X if (ifp->if_ioctl == 0)
X return (EOPNOTSUPP);
X return ((*ifp->if_ioctl)(ifp, cmd, data));
X }
X}
X
X/*
X * Initialize an interface's internet address
X * and routing table entry.
X */
Xns_ifinit(ifp, ia, sns)
X register struct ifnet *ifp;
X register struct ns_ifaddr *ia;
X struct sockaddr_ns *sns;
X{
X struct sockaddr_ns netaddr;
X register union ns_host *h = &(IA_SNS(ia)->sns_addr.x_host);
X int s = splimp(), error;
X
X /*
X * The convention we shall adopt for naming is that
X * a supplied address of zero means that "we don't care".
X * if there is a single interface, use the address of that
X * interface as our 6 byte host address.
X * if there are multiple interfaces, use any address already
X * used.
X *
X * If we have gotten into trouble and want to reset back to
X * virginity, we recognize a request of the broadcast address.
X */
X if (ns_hosteqnh(sns->sns_addr.x_host, ns_broadhost)) {
X ns_thishost = ns_zerohost;
X splx(s);
X return (0);
X }
X
X /*
X * Delete any previous route for an old address.
X */
X bzero((caddr_t)&netaddr, sizeof (netaddr));
X netaddr.sns_family = AF_NS;
X netaddr.sns_addr.x_host = ns_broadhost;
X netaddr.sns_addr.x_net = ia->ia_net;
X if (ia->ia_flags & IFA_ROUTE) {
X if ((ifp->if_flags & IFF_POINTOPOINT) == 0) {
X rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
X (int)SIOCDELRT, 0);
X } else
X rtinit(&ia->ia_dstaddr, &ia->ia_addr,
X (int)SIOCDELRT, RTF_HOST);
X }
X
X /*
X * Set up new addresses.
X */
X ia->ia_addr = *(struct sockaddr *)sns;
X ia->ia_net = sns->sns_addr.x_net;
X netaddr.sns_addr.x_net = ia->ia_net;
X if (ifp->if_flags & IFF_BROADCAST) {
X ia->ia_broadaddr = * (struct sockaddr *) &netaddr;
X }
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 (ns_hosteqnh(ns_thishost, ns_zerohost)) {
X if (ifp->if_ioctl &&
X (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
X splx(s);
X return (error);
X }
X ns_thishost = *h;
X } else if (ns_hosteqnh(sns->sns_addr.x_host, ns_zerohost)
X || ns_hosteqnh(sns->sns_addr.x_host, ns_thishost)) {
X *h = ns_thishost;
X if (ifp->if_ioctl &&
X (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
X splx(s);
X return (error);
X }
X if (!ns_hosteqnh(ns_thishost,*h)) {
X splx(s);
X return (EINVAL);
X }
X } else {
X splx(s);
X return (EINVAL);
X }
X
X /*
X * Add route for the network.
X */
X if (ifp->if_flags & IFF_POINTOPOINT)
X rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
X RTF_HOST|RTF_UP);
X else
X rtinit(&ia->ia_broadaddr, &ia->ia_addr, (int)SIOCADDRT,
X RTF_UP);
X ia->ia_flags |= IFA_ROUTE;
X return (0);
X}
X
X/*
X * Return address info for specified internet network.
X */
Xstruct ns_ifaddr *
Xns_iaonnetof(dst)
X register struct ns_addr *dst;
X{
X register struct ns_ifaddr *ia;
X register struct ns_addr *compare;
X register struct ifnet *ifp;
X struct ns_ifaddr *ia_maybe = 0;
X union ns_net net = dst->x_net;
X
X for (ia = ns_ifaddr; ia; ia = ia->ia_next) {
X if (ifp = ia->ia_ifp) {
X if (ifp->if_flags & IFF_POINTOPOINT) {
X compare = &satons_addr(ia->ia_dstaddr);
X if (ns_hosteq(*dst, *compare))
X return (ia);
X if (ns_neteqnn(net, ia->ia_net))
X ia_maybe = ia;
X } else {
X if (ns_neteqnn(net, ia->ia_net))
X return (ia);
X }
X }
X }
X return (ia_maybe);
X}
X#endif
END-of-netns/ns.c
echo x - netns/ns.h
sed 's/^X//' >netns/ns.h << 'END-of-netns/ns.h'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns.h 7.3 (Berkeley) 1/20/88
X */
X
X/*
X * Constants and Structures defined by the Xerox Network Software
X * per "Internet Transport Protocols", XSIS 028112, December 1981
X */
X
X/*
X * Protocols
X */
X#define NSPROTO_RI 1 /* Routing Information */
X#define NSPROTO_ECHO 2 /* Echo Protocol */
X#define NSPROTO_ERROR 3 /* Error Protocol */
X#define NSPROTO_PE 4 /* Packet Exchange */
X#define NSPROTO_SPP 5 /* Sequenced Packet */
X#define NSPROTO_RAW 255 /* Placemarker*/
X#define NSPROTO_MAX 256 /* Placemarker*/
X
X
X/*
X * Port/Socket numbers: network standard functions
X */
X
X#define NSPORT_RI 1 /* Routing Information */
X#define NSPORT_ECHO 2 /* Echo */
X#define NSPORT_RE 3 /* Router Error */
X
X/*
X * Ports < NSPORT_RESERVED are reserved for priveleged
X * processes (e.g. root).
X */
X#define NSPORT_RESERVED 3000
X
X/* flags passed to ns_output as last parameter */
X
X#define NS_FORWARDING 0x1 /* most of idp header exists */
X#define NS_ROUTETOIF 0x10 /* same as SO_DONTROUTE */
X#define NS_ALLOWBROADCAST SO_BROADCAST /* can send broadcast packets */
X
X#define NS_MAXHOPS 15
X
X/* flags passed to get/set socket option */
X#define SO_HEADERS_ON_INPUT 1
X#define SO_HEADERS_ON_OUTPUT 2
X#define SO_DEFAULT_HEADERS 3
X#define SO_LAST_HEADER 4
X#define SO_NSIP_ROUTE 5
X#define SO_SEQNO 6
X#define SO_ALL_PACKETS 7
X#define SO_MTU 8
X
X
X/*
X * NS addressing
X */
Xunion ns_host {
X u_char c_host[6];
X u_short s_host[3];
X};
X
Xunion ns_net {
X u_char c_net[4];
X u_short s_net[2];
X};
X
Xunion ns_net_u {
X union ns_net net_e;
X u_long long_e;
X};
X
Xstruct ns_addr {
X union ns_net x_net;
X union ns_host x_host;
X u_short x_port;
X};
X
X/*
X * Socket address, Xerox style
X */
Xstruct sockaddr_ns {
X u_short sns_family;
X struct ns_addr sns_addr;
X char sns_zero[2];
X};
X#define sns_port sns_addr.x_port
X
X#ifdef vax
X#define ns_netof(a) (*(long *) & ((a).x_net)) /* XXX - not needed */
X#endif
X#define ns_neteqnn(a,b) (((a).s_net[0]==(b).s_net[0]) && \
X ((a).s_net[1]==(b).s_net[1]))
X#define ns_neteq(a,b) ns_neteqnn((a).x_net, (b).x_net)
X#define satons_addr(sa) (((struct sockaddr_ns *)&(sa))->sns_addr)
X#define ns_hosteqnh(s,t) ((s).s_host[0] == (t).s_host[0] && \
X (s).s_host[1] == (t).s_host[1] && (s).s_host[2] == (t).s_host[2])
X#define ns_hosteq(s,t) (ns_hosteqnh((s).x_host,(t).x_host))
X#define ns_nullhost(x) (((x).x_host.s_host[0]==0) && \
X ((x).x_host.s_host[1]==0) && ((x).x_host.s_host[2]==0))
X
X#ifdef KERNEL
Xextern struct domain nsdomain;
Xunion ns_host ns_thishost;
Xunion ns_host ns_zerohost;
Xunion ns_host ns_broadhost;
Xunion ns_net ns_zeronet;
Xunion ns_net ns_broadnet;
Xu_short ns_cksum();
X#endif
END-of-netns/ns.h
echo x - netns/ns_error.c
sed 's/^X//' >netns/ns_error.c << 'END-of-netns/ns_error.c'
X/*
X * Copyright (c) 1984, 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 * @(#)ns_error.c 7.5 (Berkeley) 2/4/88
X */
X
X#include "param.h"
X#include "systm.h"
X#include "mbuf.h"
X#include "protosw.h"
X#include "socket.h"
X#include "time.h"
X#include "kernel.h"
X
X#include "../net/route.h"
X
X#include "ns.h"
X#include "ns_pcb.h"
X#include "idp.h"
X#include "ns_error.h"
X
X#ifdef lint
X#define NS_ERRPRINTFS 1
X#endif
X
X#ifdef NS_ERRPRINTFS
X/*
X * NS_ERR routines: error generation, receive packet processing, and
X * routines to turnaround packets back to the originator.
X */
Xint ns_errprintfs = 0;
X#endif
X
Xns_err_x(c)
X{
X register u_short *w, *lim, *base = ns_errstat.ns_es_codes;
X u_short x = c;
X
X /*
X * zero is a legit error code, handle specially
X */
X if (x == 0)
X return (0);
X lim = base + NS_ERR_MAX - 1;
X for (w = base + 1; w < lim; w++) {
X if (*w == 0)
X *w = x;
X if (*w == x)
X break;
X }
X return (w - base);
X}
X
X/*
X * Generate an error packet of type error
X * in response to bad packet.
X */
X
Xns_error(om, type, param)
X struct mbuf *om;
X int type;
X{
X register struct ns_epidp *ep;
X struct mbuf *m;
X struct idp *nip;
X register struct idp *oip = mtod(om, struct idp *);
X extern int idpcksum;
X
X /*
X * If this packet was sent to the echo port,
X * and nobody was there, just echo it.
X * (Yes, this is a wart!)
X */
X if (type==NS_ERR_NOSOCK &&
X oip->idp_dna.x_port==htons(2) &&
X (type = ns_echo(oip)==0))
X return;
X
X#ifdef NS_ERRPRINTFS
X if (ns_errprintfs)
X printf("ns_err_error(%x, %d, %d)\n", oip, type, param);
X#endif
X /*
X * Don't Generate error packets in response to multicasts.
X */
X if (oip->idp_dna.x_host.c_host[0] & 1)
X goto free;
X
X ns_errstat.ns_es_error++;
X /*
X * Make sure that the old IDP packet had 30 bytes of data to return;
X * if not, don't bother. Also don't EVER error if the old
X * packet protocol was NS_ERR.
X */
X if (oip->idp_len < sizeof(struct idp)) {
X ns_errstat.ns_es_oldshort++;
X goto free;
X }
X if (oip->idp_pt == NSPROTO_ERROR) {
X ns_errstat.ns_es_oldns_err++;
X goto free;
X }
X
X /*
X * First, formulate ns_err message
X */
X m = m_get(M_DONTWAIT, MT_HEADER);
X if (m == NULL)
X goto free;
X m->m_len = sizeof(*ep);
X m->m_off = MMAXOFF - m->m_len;
X ep = mtod(m, struct ns_epidp *);
X if ((u_int)type > NS_ERR_TOO_BIG)
X panic("ns_err_error");
X ns_errstat.ns_es_outhist[ns_err_x(type)]++;
X ep->ns_ep_errp.ns_err_num = htons((u_short)type);
X ep->ns_ep_errp.ns_err_param = htons((u_short)param);
X bcopy((caddr_t)oip, (caddr_t)&ep->ns_ep_errp.ns_err_idp, 42);
X nip = &ep->ns_ep_idp;
X nip->idp_len = sizeof(*ep);
X nip->idp_len = htons((u_short)nip->idp_len);
X nip->idp_pt = NSPROTO_ERROR;
X nip->idp_tc = 0;
X nip->idp_dna = oip->idp_sna;
X nip->idp_sna = oip->idp_dna;
X if (idpcksum) {
X nip->idp_sum = 0;
X nip->idp_sum = ns_cksum(dtom(nip), sizeof(*ep));
X } else
X nip->idp_sum = 0xffff;
X (void) ns_output(dtom(nip), (struct route *)0, 0);
X
Xfree:
X m_freem(dtom(oip));
X}
X
Xns_printhost(p)
Xregister struct ns_addr *p;
X{
X
X printf("<net:%x%x,host:%x%x%x,port:%x>",
X p->x_net.s_net[0],
X p->x_net.s_net[1],
X p->x_host.s_host[0],
X p->x_host.s_host[1],
X p->x_host.s_host[2],
X p->x_port);
X
X}
X
X/*
X * Process a received NS_ERR message.
X */
Xns_err_input(m)
X struct mbuf *m;
X{
X register struct ns_errp *ep;
X register struct ns_epidp *epidp = mtod(m, struct ns_epidp *);
X register int i;
X int type, code, param;
X
X /*
X * Locate ns_err structure in mbuf, and check
X * that not corrupted and of at least minimum length.
X */
X#ifdef NS_ERRPRINTFS
X if (ns_errprintfs) {
X printf("ns_err_input from ");
X ns_printhost(&epidp->ns_ep_idp.idp_sna);
X printf("len %d\n", ntohs(epidp->ns_ep_idp.idp_len));
X }
X#endif
X i = sizeof (struct ns_epidp);
X if ((m->m_off > MMAXOFF || m->m_len < i) &&
X (m = m_pullup(m, i)) == 0) {
X ns_errstat.ns_es_tooshort++;
X return;
X }
X ep = &(mtod(m, struct ns_epidp *)->ns_ep_errp);
X type = ntohs(ep->ns_err_num);
X param = ntohs(ep->ns_err_param);
X ns_errstat.ns_es_inhist[ns_err_x(type)]++;
X
X#ifdef NS_ERRPRINTFS
X /*
X * Message type specific processing.
X */
X if (ns_errprintfs)
X printf("ns_err_input, type %d param %d\n", type, param);
X#endif
X if (type >= NS_ERR_TOO_BIG) {
X goto badcode;
X }
X ns_errstat.ns_es_outhist[ns_err_x(type)]++;
X switch (type) {
X
X case NS_ERR_UNREACH_HOST:
X code = PRC_UNREACH_NET;
X goto deliver;
X
X case NS_ERR_TOO_OLD:
X code = PRC_TIMXCEED_INTRANS;
X goto deliver;
X
X case NS_ERR_TOO_BIG:
X code = PRC_MSGSIZE;
X goto deliver;
X
X case NS_ERR_FULLUP:
X code = PRC_QUENCH;
X goto deliver;
X
X case NS_ERR_NOSOCK:
X code = PRC_UNREACH_PORT;
X goto deliver;
X
X case NS_ERR_UNSPEC_T:
X case NS_ERR_BADSUM_T:
X case NS_ERR_BADSUM:
X case NS_ERR_UNSPEC:
X code = PRC_PARAMPROB;
X goto deliver;
X
X deliver:
X /*
X * Problem with datagram; advise higher level routines.
X */
X#ifdef NS_ERRPRINTFS
X if (ns_errprintfs)
X printf("deliver to protocol %d\n",
X ep->ns_err_idp.idp_pt);
X#endif
X switch(ep->ns_err_idp.idp_pt) {
X case NSPROTO_SPP:
X spp_ctlinput(code, (caddr_t)ep);
X break;
X
X default:
X idp_ctlinput(code, (caddr_t)ep);
X }
X
X goto free;
X
X default:
X badcode:
X ns_errstat.ns_es_badcode++;
X goto free;
X
X }
Xfree:
X m_freem(m);
X}
X
X#ifdef notdef
Xu_long
Xnstime()
X{
X int s = splclock();
X u_long t;
X
X t = (time.tv_sec % (24*60*60)) * 1000 + time.tv_usec / 1000;
X splx(s);
X return (htonl(t));
X}
X#endif
X
Xns_echo(idp)
Xregister struct idp *idp;
X{
X struct mbuf *m = dtom(idp);
X register struct echo {
X struct idp ec_idp;
X u_short ec_op; /* Operation, 1 = request, 2 = reply */
X } *ec = (struct echo *)idp;
X struct ns_addr temp;
X
X if (idp->idp_pt!=NSPROTO_ECHO) return(NS_ERR_NOSOCK);
X if (ec->ec_op!=htons(1)) return(NS_ERR_UNSPEC);
X
X ec->ec_op = htons(2);
X
X temp = idp->idp_dna;
X idp->idp_dna = idp->idp_sna;
X idp->idp_sna = temp;
X
X if (idp->idp_sum != 0xffff) {
X idp->idp_sum = 0;
X idp->idp_sum = ns_cksum(m,
X (int)(((ntohs(idp->idp_len) - 1)|1)+1));
X }
X (void) ns_output(m, (struct route *)0, NS_FORWARDING);
X return(0);
X}
END-of-netns/ns_error.c
echo x - netns/ns_error.h
sed 's/^X//' >netns/ns_error.h << 'END-of-netns/ns_error.h'
X/*
X * Copyright (c) 1984, 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 * @(#)ns_error.h 7.3 (Berkeley) 1/28/88
X */
X
X/*
X * Xerox NS error messages
X */
X
Xstruct ns_errp {
X u_short ns_err_num; /* Error Number */
X u_short ns_err_param; /* Error Parameter */
X struct idp ns_err_idp; /* Initial segment of offending
X packet */
X u_char ns_err_lev2[12]; /* at least this much higher
X level protocol */
X};
Xstruct ns_epidp {
X struct idp ns_ep_idp;
X struct ns_errp ns_ep_errp;
X};
X
X#define NS_ERR_UNSPEC 0 /* Unspecified Error detected at dest. */
X#define NS_ERR_BADSUM 1 /* Bad Checksum detected at dest */
X#define NS_ERR_NOSOCK 2 /* Specified socket does not exist at dest*/
X#define NS_ERR_FULLUP 3 /* Dest. refuses packet due to resource lim.*/
X#define NS_ERR_UNSPEC_T 0x200 /* Unspec. Error occured before reaching dest*/
X#define NS_ERR_BADSUM_T 0x201 /* Bad Checksum detected in transit */
X#define NS_ERR_UNREACH_HOST 0x202 /* Dest cannot be reached from here*/
X#define NS_ERR_TOO_OLD 0x203 /* Packet x'd 15 routers without delivery*/
X#define NS_ERR_TOO_BIG 0x204 /* Packet too large to be forwarded through
X some intermediate gateway. The error
X parameter field contains the max packet
X size that can be accommodated */
X#define NS_ERR_MAX 20
X
X/*
X * Variables related to this implementation
X * of the network systems error message protocol.
X */
Xstruct ns_errstat {
X/* statistics related to ns_err packets generated */
X int ns_es_error; /* # of calls to ns_error */
X int ns_es_oldshort; /* no error 'cuz old ip too short */
X int ns_es_oldns_err; /* no error 'cuz old was ns_err */
X int ns_es_outhist[NS_ERR_MAX];
X/* statistics related to input messages processed */
X int ns_es_badcode; /* ns_err_code out of range */
X int ns_es_tooshort; /* packet < IDP_MINLEN */
X int ns_es_checksum; /* bad checksum */
X int ns_es_badlen; /* calculated bound mismatch */
X int ns_es_reflect; /* number of responses */
X int ns_es_inhist[NS_ERR_MAX];
X u_short ns_es_codes[NS_ERR_MAX];/* which error code for outhist
X since we might not know all */
X};
X
X#ifdef KERNEL
Xstruct ns_errstat ns_errstat;
X#endif
END-of-netns/ns_error.h
echo x - netns/ns_if.h
sed 's/^X//' >netns/ns_if.h << 'END-of-netns/ns_if.h'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns_if.h 7.2 (Berkeley) 1/20/88
X */
X
X/*
X * Interface address, xerox 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 */
X
Xstruct ns_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 union ns_net ia_net; /* network number of interface */
X int ia_flags;
X struct ns_ifaddr *ia_next; /* next in list of internet addresses */
X};
X
X/*
X * Given a pointer to an ns_ifaddr (ifaddr),
X * return a pointer to the addr as a sockadd_ns.
X */
X
X#define IA_SNS(ia) ((struct sockaddr_ns *)(&((struct ns_ifaddr *)ia)->ia_addr))
X/*
X * ia_flags
X */
X#define IFA_ROUTE 0x01 /* routing entry installed */
X
X/* This is not the right place for this but where is? */
X#define ETHERTYPE_NS 0x0600
X
X#ifdef NSIP
Xstruct nsip_req {
X struct sockaddr rq_ns; /* must be ns format destination */
X struct sockaddr rq_ip; /* must be ip format gateway */
X short rq_flags;
X};
X#endif
X
X#ifdef KERNEL
Xstruct ns_ifaddr *ns_ifaddr;
Xstruct ns_ifaddr *ns_iaonnetof();
Xstruct ifqueue nsintrq; /* XNS input packet queue */
X#endif
END-of-netns/ns_if.h
echo x - netns/ns_input.c
sed 's/^X//' >netns/ns_input.c << 'END-of-netns/ns_input.c'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns_input.c 7.2 (Berkeley) 1/20/88
X */
X
X#include "param.h"
X#include "systm.h"
X#include "mbuf.h"
X#include "domain.h"
X#include "protosw.h"
X#include "socket.h"
X#include "socketvar.h"
X#include "errno.h"
X#include "time.h"
X#include "kernel.h"
X
X#include "../net/if.h"
X#include "../net/route.h"
X#include "../net/raw_cb.h"
X
X#include "ns.h"
X#include "ns_if.h"
X#include "ns_pcb.h"
X#include "idp.h"
X#include "idp_var.h"
X#include "ns_error.h"
X
X/*
X * NS initialization.
X */
Xunion ns_host ns_thishost;
Xunion ns_host ns_zerohost;
Xunion ns_host ns_broadhost;
Xunion ns_net ns_zeronet;
Xunion ns_net ns_broadnet;
X
Xstatic u_short allones[] = {-1, -1, -1};
X
Xstruct nspcb nspcb;
Xstruct nspcb nsrawpcb;
X
Xstruct ifqueue nsintrq;
Xint nsqmaxlen = IFQ_MAXLEN;
X
Xint idpcksum = 1;
Xlong ns_pexseq;
X
Xns_init()
X{
X extern struct timeval time;
X
X ns_broadhost = * (union ns_host *) allones;
X ns_broadnet = * (union ns_net *) allones;
X nspcb.nsp_next = nspcb.nsp_prev = &nspcb;
X nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb;
X nsintrq.ifq_maxlen = nsqmaxlen;
X ns_pexseq = time.tv_usec;
X}
X
X/*
X * Idp input routine. Pass to next level.
X */
Xint nsintr_getpck = 0;
Xint nsintr_swtch = 0;
Xnsintr()
X{
X register struct idp *idp;
X register struct mbuf *m;
X register struct nspcb *nsp;
X struct ifnet *ifp;
X struct mbuf *m0;
X register int i;
X int len, s, error;
X char oddpacketp;
X
Xnext:
X /*
X * Get next datagram off input queue and get IDP header
X * in first mbuf.
X */
X s = splimp();
X IF_DEQUEUEIF(&nsintrq, m, ifp);
X splx(s);
X nsintr_getpck++;
X if (m == 0)
X return;
X if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct idp)) &&
X (m = m_pullup(m, sizeof (struct idp))) == 0) {
X idpstat.idps_toosmall++;
X goto next;
X }
X
X /*
X * Give any raw listeners a crack at the packet
X */
X for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
X struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL);
X if (m1) idp_input(m1, nsp, ifp);
X }
X
X idp = mtod(m, struct idp *);
X len = ntohs(idp->idp_len);
X if (oddpacketp = len & 1) {
X len++; /* If this packet is of odd length,
X preserve garbage byte for checksum */
X }
X
X /*
X * Check that the amount of data in the buffers
X * is as at least much as the IDP header would have us expect.
X * Trim mbufs if longer than we expect.
X * Drop packet if shorter than we expect.
X */
X i = -len;
X m0 = m;
X for (;;) {
X i += m->m_len;
X if (m->m_next == 0)
X break;
X m = m->m_next;
X }
X if (i != 0) {
X if (i < 0) {
X idpstat.idps_tooshort++;
X m = m0;
X goto bad;
X }
X if (i <= m->m_len)
X m->m_len -= i;
X else
X m_adj(m0, -i);
X }
X m = m0;
X if (idpcksum && ((i = idp->idp_sum)!=0xffff)) {
X idp->idp_sum = 0;
X if (i != (idp->idp_sum = ns_cksum(m,len))) {
X idpstat.idps_badsum++;
X idp->idp_sum = i;
X if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host))
X error = NS_ERR_BADSUM;
X else
X error = NS_ERR_BADSUM_T;
X ns_error(m, error, 0);
X goto next;
X }
X }
X /*
X * Is this a directed broadcast?
X */
X if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) {
X if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) &&
X (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) &&
X (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) &&
X (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) {
X /*
X * Look to see if I need to eat this packet.
X * Algorithm is to forward all young packets
X * and prematurely age any packets which will
X * by physically broadcasted.
X * Any very old packets eaten without forwarding
X * would die anyway.
X *
X * Suggestion of Bill Nesheim, Cornell U.
X */
X if (idp->idp_tc < NS_MAXHOPS) {
X idp_forward(idp);
X goto next;
X }
X }
X /*
X * Is this our packet? If not, forward.
X */
X } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) {
X idp_forward(idp);
X goto next;
X }
X /*
X * Locate pcb for datagram.
X */
X nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD);
X /*
X * Switch out to protocol's input routine.
X */
X nsintr_swtch++;
X if (nsp) {
X if (oddpacketp) {
X m_adj(m0, -1);
X }
X if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0)
X switch (idp->idp_pt) {
X
X case NSPROTO_SPP:
X spp_input(m, nsp, ifp);
X goto next;
X
X case NSPROTO_ERROR:
X ns_err_input(m);
X goto next;
X }
X idp_input(m, nsp, ifp);
X } else {
X ns_error(m, NS_ERR_NOSOCK, 0);
X }
X goto next;
X
Xbad:
X m_freem(m);
X goto next;
X}
X
Xu_char nsctlerrmap[PRC_NCMDS] = {
X ECONNABORTED, ECONNABORTED, 0, 0,
X 0, 0, EHOSTDOWN, EHOSTUNREACH,
X ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED,
X EMSGSIZE, 0, 0, 0,
X 0, 0, 0, 0
X};
X
Xidp_donosocks = 1;
X
Xidp_ctlinput(cmd, arg)
X int cmd;
X caddr_t arg;
X{
X struct ns_addr *ns;
X struct nspcb *nsp;
X struct ns_errp *errp;
X int idp_abort();
X extern struct nspcb *idp_drop();
X int type;
X
X if (cmd < 0 || cmd > PRC_NCMDS)
X return;
X if (nsctlerrmap[cmd] == 0)
X return; /* XXX */
X type = NS_ERR_UNREACH_HOST;
X switch (cmd) {
X struct sockaddr_ns *sns;
X
X case PRC_IFDOWN:
X case PRC_HOSTDEAD:
X case PRC_HOSTUNREACH:
X sns = (struct sockaddr_ns *)arg;
X if (sns->sns_family != AF_INET)
X return;
X ns = &sns->sns_addr;
X break;
X
X default:
X errp = (struct ns_errp *)arg;
X ns = &errp->ns_err_idp.idp_dna;
X type = errp->ns_err_num;
X type = ntohs((u_short)type);
X }
X switch (type) {
X
X case NS_ERR_UNREACH_HOST:
X ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0);
X break;
X
X case NS_ERR_NOSOCK:
X nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port,
X NS_WILDCARD);
X if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr))
X (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
X }
X}
X
Xint idpprintfs = 0;
Xint idpforwarding = 1;
X/*
X * Forward a packet. If some error occurs return the sender
X * an error packet. Note we can't always generate a meaningful
X * error message because the NS errors don't have a large enough repetoire
X * of codes and types.
X */
Xstruct route idp_droute;
Xstruct route idp_sroute;
X
Xidp_forward(idp)
X register struct idp *idp;
X{
X register int error, type, code;
X struct mbuf *mcopy = NULL;
X int agedelta = 1;
X int flags = NS_FORWARDING;
X int ok_there = 0;
X int ok_back = 0;
X
X if (idpprintfs) {
X printf("forward: src ");
X ns_printhost(&idp->idp_sna);
X printf(", dst ");
X ns_printhost(&idp->idp_dna);
X printf("hop count %d\n", idp->idp_tc);
X }
X if (idpforwarding == 0) {
X /* can't tell difference between net and host */
X type = NS_ERR_UNREACH_HOST, code = 0;
X goto senderror;
X }
X idp->idp_tc++;
X if (idp->idp_tc > NS_MAXHOPS) {
X type = NS_ERR_TOO_OLD, code = 0;
X goto senderror;
X }
X /*
X * Save at most 42 bytes of the packet in case
X * we need to generate an NS error message to the src.
X */
X mcopy = m_copy(dtom(idp), 0, imin((int)ntohs(idp->idp_len), 42));
X
X if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) {
X type = NS_ERR_UNREACH_HOST, code = 0;
X goto senderror;
X }
X /*
X * Here we think about forwarding broadcast packets,
X * so we try to insure that it doesn't go back out
X * on the interface it came in on. Also, if we
X * are going to physically broadcast this, let us
X * age the packet so we can eat it safely the second time around.
X */
X if (idp->idp_dna.x_host.c_host[0] & 0x1) {
X struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
X struct ifnet *ifp;
X if (ia) {
X /* I'm gonna hafta eat this packet */
X agedelta += NS_MAXHOPS - idp->idp_tc;
X idp->idp_tc = NS_MAXHOPS;
X }
X if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) {
X /* error = ENETUNREACH; He'll never get it! */
X m_freem(dtom(idp));
X goto cleanup;
X }
X if (idp_droute.ro_rt &&
X (ifp=idp_droute.ro_rt->rt_ifp) &&
X idp_sroute.ro_rt &&
X (ifp!=idp_sroute.ro_rt->rt_ifp)) {
X flags |= NS_ALLOWBROADCAST;
X } else {
X type = NS_ERR_UNREACH_HOST, code = 0;
X goto senderror;
X }
X }
X /* need to adjust checksum */
X if (idp->idp_sum!=0xffff) {
X union bytes {
X u_char c[4];
X u_short s[2];
X long l;
X } x;
X register int shift;
X x.l = 0; x.c[0] = agedelta;
X shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf;
X x.l = idp->idp_sum + (x.l << shift);
X x.l = x.s[0] + x.s[1];
X x.l = x.s[0] + x.s[1];
X if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l;
X }
X if ((error = ns_output(dtom(idp), &idp_droute, flags)) &&
X (mcopy!=NULL)) {
X idp = mtod(mcopy, struct idp *);
X type = NS_ERR_UNSPEC_T, code = 0;
X switch (error) {
X
X case ENETUNREACH:
X case EHOSTDOWN:
X case EHOSTUNREACH:
X case ENETDOWN:
X case EPERM:
X type = NS_ERR_UNREACH_HOST;
X break;
X
X case EMSGSIZE:
X type = NS_ERR_TOO_BIG;
X code = 576; /* too hard to figure out mtu here */
X break;
X
X case ENOBUFS:
X type = NS_ERR_UNSPEC_T;
X break;
X }
X mcopy = NULL;
X senderror:
X ns_error(dtom(idp), type, code);
X }
Xcleanup:
X if (ok_there)
X idp_undo_route(&idp_droute);
X if (ok_back)
X idp_undo_route(&idp_sroute);
X if (mcopy != NULL)
X m_freem(mcopy);
X}
X
Xidp_do_route(src, ro)
Xstruct ns_addr *src;
Xstruct route *ro;
X{
X
X struct sockaddr_ns *dst;
X
X bzero((caddr_t)ro, sizeof (*ro));
X dst = (struct sockaddr_ns *)&ro->ro_dst;
X
X dst->sns_family = AF_NS;
X dst->sns_addr = *src;
X dst->sns_addr.x_port = 0;
X rtalloc(ro);
X if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) {
X return (0);
X }
X ro->ro_rt->rt_use++;
X return (1);
X}
X
Xidp_undo_route(ro)
Xregister struct route *ro;
X{
X if (ro->ro_rt) {RTFREE(ro->ro_rt);}
X}
Xstatic union ns_net
Xns_zeronet;
X
Xns_watch_output(m, ifp)
Xstruct mbuf *m;
Xstruct ifnet *ifp;
X{
X register struct nspcb *nsp;
X register struct ifaddr *ia;
X /*
X * Give any raw listeners a crack at the packet
X */
X for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
X struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL);
X if (m0) {
X struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
X
X if(m1 == NULL)
X m_freem(m0);
X else {
X register struct idp *idp;
X
X m1->m_off = MMINOFF;
X m1->m_len = sizeof (*idp);
X m1->m_next = m0;
X idp = mtod(m1, struct idp *);
X idp->idp_sna.x_net = ns_zeronet;
X idp->idp_sna.x_host = ns_thishost;
X if (ifp && (ifp->if_flags & IFF_POINTOPOINT))
X for(ia = ifp->if_addrlist; ia;
X ia = ia->ifa_next) {
X if (ia->ifa_addr.sa_family==AF_NS) {
X idp->idp_sna =
X satons_addr(ia->ifa_dstaddr);
X break;
X }
X }
X idp->idp_len = 0xffff;
X idp_input(m1, nsp, ifp);
X }
X }
X }
X}
END-of-netns/ns_input.c
echo x - netns/ns_ip.c
sed 's/^X//' >netns/ns_ip.c << 'END-of-netns/ns_ip.c'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns_ip.c 7.2 (Berkeley) 1/20/88
X */
X
X/*
X * Software interface driver for encapsulating ns in ip.
X */
X
X#ifdef NSIP
X#include "param.h"
X#include "systm.h"
X#include "mbuf.h"
X#include "socket.h"
X#include "socketvar.h"
X#include "errno.h"
X#include "ioctl.h"
X#include "protosw.h"
X
X#include "../net/if.h"
X#include "../net/netisr.h"
X#include "../net/route.h"
X
X#include "../netinet/in.h"
X#include "../netinet/in_systm.h"
X#include "../netinet/in_var.h"
X#include "../netinet/ip.h"
X#include "../netinet/ip_var.h"
X
X#ifdef vax
X#include "../vax/mtpr.h"
X#endif
X
X#include "../netns/ns.h"
X#include "../netns/ns_if.h"
X#include "../netns/idp.h"
X
Xstruct ifnet_en {
X struct ifnet ifen_ifnet;
X struct route ifen_route;
X struct in_addr ifen_src;
X struct in_addr ifen_dst;
X};
X
Xint nsipoutput(), nsipioctl();
X#define LOMTU (1024+512);
X
Xstruct ifnet nsipif;
Xstruct mbuf *nsip_list; /* list of all hosts and gateways or
X broadcast addrs */
X
Xstruct mbuf *
Xnsipattach()
X{
X register struct mbuf *m = m_getclr(M_DONTWAIT, MT_PCB);
X register struct ifnet *ifp;
X
X if (m == NULL) return (NULL);
X m->m_off = MMINOFF;
X m->m_len = sizeof(struct ifnet_en);
X m->m_next = nsip_list;
X nsip_list = m;
X ifp = mtod(m, struct ifnet *);
X
X ifp->if_name = "nsip";
X ifp->if_mtu = LOMTU;
X ifp->if_ioctl = nsipioctl;
X ifp->if_output = nsipoutput;
X ifp->if_flags = IFF_POINTOPOINT;
X ifp->if_unit = nsipif.if_unit++;
X if_attach(ifp);
X return (dtom(ifp));
X}
X
X
X/*
X * Process an ioctl request.
X */
X/* ARGSUSED */
Xnsipioctl(ifp, cmd, data)
X register struct ifnet *ifp;
X int cmd;
X caddr_t data;
X{
X int error = 0;
X struct ifreq *ifr;
X
X switch (cmd) {
X
X case SIOCSIFADDR:
X ifp->if_flags |= IFF_UP;
X /* fall into: */
X
X case SIOCSIFDSTADDR:
X /*
X * Everything else is done at a higher level.
X */
X break;
X
X case SIOCSIFFLAGS:
X ifr = (struct ifreq *)data;
X if ((ifr->ifr_flags & IFF_UP) == 0)
X error = nsip_free(ifp);
X
X
X default:
X error = EINVAL;
X }
X return (error);
X}
X
Xstruct mbuf *nsip_badlen;
Xstruct mbuf *nsip_lastin;
Xint nsip_hold_input;
X
Xidpip_input(m, ifp)
X register struct mbuf *m;
X struct ifnet *ifp;
X{
X register struct ip *ip;
X register struct idp *idp;
X register struct ifqueue *ifq = &nsintrq;
X int len, s;
X
X if (nsip_hold_input) {
X if (nsip_lastin) {
X m_freem(nsip_lastin);
X }
X nsip_lastin = m_copy(m, 0, (int)M_COPYALL);
X }
X /*
X * Get IP and IDP header together in first mbuf.
X */
X nsipif.if_ipackets++;
X s = sizeof (struct ip) + sizeof (struct idp);
X if ((m->m_off > MMAXOFF || m->m_len < s) &&
X (m = m_pullup(m, s)) == 0) {
X nsipif.if_ierrors++;
X return;
X }
X ip = mtod(m, struct ip *);
X if (ip->ip_hl > (sizeof (struct ip) >> 2)) {
X ip_stripoptions(ip, (struct mbuf *)0);
X if (m->m_len < s) {
X if ((m = m_pullup(m, s)) == 0) {
X nsipif.if_ierrors++;
X return;
X }
X ip = mtod(m, struct ip *);
X }
X }
X
X /*
X * Make mbuf data length reflect IDP length.
X * If not enough data to reflect IDP length, drop.
X */
X m->m_off += sizeof (struct ip);
X m->m_len -= sizeof (struct ip);
X idp = mtod(m, struct idp *);
X len = ntohs(idp->idp_len);
X if (len & 1) len++; /* Preserve Garbage Byte */
X if (ip->ip_len != len) {
X if (len > ip->ip_len) {
X nsipif.if_ierrors++;
X if (nsip_badlen) m_freem(nsip_badlen);
X nsip_badlen = m;
X return;
X }
X /* Any extra will be trimmed off by the NS routines */
X }
X
X /*
X * Place interface pointer before the data
X * for the receiving protocol.
X */
X if (m->m_off >= MMINOFF + sizeof(struct ifnet *)) {
X m->m_off -= sizeof(struct ifnet *);
X m->m_len += sizeof(struct ifnet *);
X } else {
X struct mbuf *n;
X
X n = m_get(M_DONTWAIT, MT_HEADER);
X if (n == (struct mbuf *)0)
X goto bad;
X n->m_off = MMINOFF;
X n->m_len = sizeof(struct ifnet *);
X n->m_next = m;
X m = n;
X }
X *(mtod(m, struct ifnet **)) = ifp;
X
X /*
X * Deliver to NS
X */
X s = splimp();
X if (IF_QFULL(ifq)) {
X IF_DROP(ifq);
Xbad:
X m_freem(m);
X splx(s);
X return;
X }
X IF_ENQUEUE(ifq, m);
X schednetisr(NETISR_NS);
X splx(s);
X return;
X}
X
X/* ARGSUSED */
Xnsipoutput(ifn, m0, dst)
X struct ifnet_en *ifn;
X struct mbuf *m0;
X struct sockaddr *dst;
X{
X
X register struct mbuf *m = dtom(ifn);
X register struct ip *ip;
X register struct route *ro = &(ifn->ifen_route);
X register int len = 0;
X register struct idp *idp = mtod(m0, struct idp *);
X int error;
X
X if (m->m_len != sizeof(struct ifnet_en)) {
X printf("nsipoutput: bad dst ifp %x\n", ifn);
X goto bad;
X }
X ifn->ifen_ifnet.if_opackets++;
X nsipif.if_opackets++;
X
X
X /*
X * Calculate data length and make space
X * for IP header.
X */
X len = ntohs(idp->idp_len);
X if (len & 1) len++; /* Preserve Garbage Byte */
X m = m0;
X if (m->m_off < MMINOFF + sizeof (struct ip)) {
X m = m_get(M_DONTWAIT, MT_HEADER);
X if (m == 0) {
X m_freem(m0);
X return (ENOBUFS);
X }
X m->m_off = MMAXOFF - sizeof (struct ip);
X m->m_len = sizeof (struct ip);
X m->m_next = m0;
X } else {
X m->m_off -= sizeof (struct ip);
X m->m_len += sizeof (struct ip);
X }
X /*
X * Fill in IP header.
X */
X ip = mtod(m, struct ip *);
X *(long *)ip = 0;
X ip->ip_p = IPPROTO_IDP;
X ip->ip_src = ifn->ifen_src;
X ip->ip_dst = ifn->ifen_dst;
X ip->ip_len = (u_short)len + sizeof (struct ip);
X ip->ip_ttl = MAXTTL;
X
X /*
X * Output final datagram.
X */
X error = (ip_output(m, (struct mbuf *)0, ro, SO_BROADCAST));
X if (error) {
X ifn->ifen_ifnet.if_oerrors++;
X ifn->ifen_ifnet.if_ierrors = error;
X }
X return (error);
Xbad:
X m_freem(m0);
X return (ENETUNREACH);
X}
X
Xstruct ifreq ifr = {"nsip0"};
X
Xnsip_route(m)
X register struct mbuf *m;
X{
X register struct nsip_req *rq = mtod(m, struct nsip_req *);
X struct sockaddr_ns *ns_dst = (struct sockaddr_ns *)&rq->rq_ns;
X struct sockaddr_in *ip_dst = (struct sockaddr_in *)&rq->rq_ip;
X struct route ro;
X struct ifnet_en *ifn;
X struct sockaddr_in *src;
X
X /*
X * First, make sure we already have an ns address:
X */
X if (ns_hosteqnh(ns_thishost, ns_zerohost))
X return (EADDRNOTAVAIL);
X /*
X * Now, determine if we can get to the destination
X */
X bzero((caddr_t)&ro, sizeof (ro));
X ro.ro_dst = *(struct sockaddr *)ip_dst;
X rtalloc(&ro);
X if (ro.ro_rt == 0 || ro.ro_rt->rt_ifp == 0) {
X return (ENETUNREACH);
X }
X
X /*
X * And see how he's going to get back to us:
X * i.e., what return ip address do we use?
X */
X {
X register struct in_ifaddr *ia;
X struct ifnet *ifp = ro.ro_rt->rt_ifp;
X
X for (ia = in_ifaddr; ia; ia = ia->ia_next)
X if (ia->ia_ifp == ifp)
X break;
X if (ia == 0)
X ia = in_ifaddr;
X if (ia == 0) {
X RTFREE(ro.ro_rt);
X return (EADDRNOTAVAIL);
X }
X src = (struct sockaddr_in *)&ia->ia_addr;
X }
X
X /*
X * Is there a free (pseudo-)interface or space?
X */
X for (m = nsip_list; m; m = m->m_next) {
X struct ifnet *ifp = mtod(m, struct ifnet *);
X if ((ifp->if_flags & IFF_UP) == 0)
X break;
X }
X if (m == (struct mbuf *) 0)
X m = nsipattach();
X if (m == NULL) {
X RTFREE(ro.ro_rt);
X return (ENOBUFS);
X }
X ifn = mtod(m, struct ifnet_en *);
X
X ifn->ifen_route = ro;
X ifn->ifen_dst = ip_dst->sin_addr;
X ifn->ifen_src = src->sin_addr;
X
X /*
X * now configure this as a point to point link
X */
X ifr.ifr_name[4] = '0' + nsipif.if_unit - 1;
X ifr.ifr_dstaddr = * (struct sockaddr *) ns_dst;
X (void)ns_control((struct socket *)0, (int)SIOCSIFDSTADDR, (caddr_t)&ifr,
X (struct ifnet *)ifn);
X satons_addr(ifr.ifr_addr).x_host = ns_thishost;
X return (ns_control((struct socket *)0, (int)SIOCSIFADDR, (caddr_t)&ifr,
X (struct ifnet *)ifn));
X}
X
Xnsip_free(ifp)
Xstruct ifnet *ifp;
X{
X register struct ifnet_en *ifn = (struct ifnet_en *)ifp;
X struct route *ro = & ifn->ifen_route;
X
X if (ro->ro_rt) {
X RTFREE(ro->ro_rt);
X ro->ro_rt = 0;
X }
X ifp->if_flags &= ~IFF_UP;
X return (0);
X}
X
Xnsip_ctlinput(cmd, sa)
X int cmd;
X struct sockaddr *sa;
X{
X extern u_char inetctlerrmap[];
X struct sockaddr_in *sin;
X int in_rtchange();
X
X if ((unsigned)cmd >= PRC_NCMDS)
X return;
X if (sa->sa_family != AF_INET && sa->sa_family != AF_IMPLINK)
X return;
X sin = (struct sockaddr_in *)sa;
X if (sin->sin_addr.s_addr == INADDR_ANY)
X return;
X
X switch (cmd) {
X
X case PRC_ROUTEDEAD:
X case PRC_REDIRECT_NET:
X case PRC_REDIRECT_HOST:
X case PRC_REDIRECT_TOSNET:
X case PRC_REDIRECT_TOSHOST:
X nsip_rtchange(&sin->sin_addr);
X break;
X }
X}
X
Xnsip_rtchange(dst)
X register struct in_addr *dst;
X{
X register struct mbuf *m;
X register struct ifnet_en *ifn;
X
X for (m = nsip_list; m; m = m->m_next) {
X ifn = mtod(m, struct ifnet_en *);
X if (ifn->ifen_dst.s_addr == dst->s_addr &&
X ifn->ifen_route.ro_rt) {
X RTFREE(ifn->ifen_route.ro_rt);
X ifn->ifen_route.ro_rt = 0;
X }
X }
X}
X#endif
END-of-netns/ns_ip.c
echo x - netns/ns_output.c
sed 's/^X//' >netns/ns_output.c << 'END-of-netns/ns_output.c'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns_output.c 7.2 (Berkeley) 1/20/88
X */
X
X#include "param.h"
X#include "mbuf.h"
X#include "errno.h"
X#include "socket.h"
X#include "socketvar.h"
X
X#include "../net/if.h"
X#include "../net/route.h"
X
X#include "ns.h"
X#include "ns_if.h"
X#include "idp.h"
X#include "idp_var.h"
X
X#ifdef vax
X#include "../vax/mtpr.h"
X#endif
Xint ns_hold_output = 0;
Xint ns_copy_output = 0;
Xint ns_output_cnt = 0;
Xstruct mbuf *ns_lastout;
X
Xns_output(m0, ro, flags)
X struct mbuf *m0;
X struct route *ro;
X int flags;
X{
X register struct idp *idp = mtod(m0, struct idp *);
X register struct ifnet *ifp = 0;
X int error = 0;
X struct route idproute;
X struct sockaddr_ns *dst;
X extern int idpcksum;
X
X if (ns_hold_output) {
X if (ns_lastout) {
X (void)m_free(ns_lastout);
X }
X ns_lastout = m_copy(m0, 0, (int)M_COPYALL);
X }
X /*
X * Route packet.
X */
X if (ro == 0) {
X ro = &idproute;
X bzero((caddr_t)ro, sizeof (*ro));
X }
X dst = (struct sockaddr_ns *)&ro->ro_dst;
X if (ro->ro_rt == 0) {
X dst->sns_family = AF_NS;
X dst->sns_addr = idp->idp_dna;
X dst->sns_addr.x_port = 0;
X /*
X * If routing to interface only,
X * short circuit routing lookup.
X */
X if (flags & NS_ROUTETOIF) {
X struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
X
X if (ia == 0) {
X error = ENETUNREACH;
X goto bad;
X }
X ifp = ia->ia_ifp;
X goto gotif;
X }
X rtalloc(ro);
X } else if ((ro->ro_rt->rt_flags & RTF_UP) == 0) {
X /*
X * The old route has gone away; try for a new one.
X */
X rtfree(ro->ro_rt);
X ro->ro_rt = NULL;
X rtalloc(ro);
X }
X if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
X error = ENETUNREACH;
X goto bad;
X }
X ro->ro_rt->rt_use++;
X if (ro->ro_rt->rt_flags & (RTF_GATEWAY|RTF_HOST))
X dst = (struct sockaddr_ns *)&ro->ro_rt->rt_gateway;
Xgotif:
X
X /*
X * Look for multicast addresses and
X * and verify user is allowed to send
X * such a packet.
X */
X if (dst->sns_addr.x_host.c_host[0]&1) {
X if ((ifp->if_flags & IFF_BROADCAST) == 0) {
X error = EADDRNOTAVAIL;
X goto bad;
X }
X if ((flags & NS_ALLOWBROADCAST) == 0) {
X error = EACCES;
X goto bad;
X }
X }
X
X if (htons(idp->idp_len) <= ifp->if_mtu) {
X ns_output_cnt++;
X if (ns_copy_output) {
X ns_watch_output(m0, ifp);
X }
X error = (*ifp->if_output)(ifp, m0, (struct sockaddr *)dst);
X goto done;
X } else error = EMSGSIZE;
X
X
Xbad:
X if (ns_copy_output) {
X ns_watch_output(m0, ifp);
X }
X m_freem(m0);
Xdone:
X if (ro == &idproute && (flags & NS_ROUTETOIF) == 0 && ro->ro_rt)
X RTFREE(ro->ro_rt);
X return (error);
X}
END-of-netns/ns_output.c
echo x - netns/ns_pcb.c
sed 's/^X//' >netns/ns_pcb.c << 'END-of-netns/ns_pcb.c'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns_pcb.c 7.3 (Berkeley) 1/20/88
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 "../net/if.h"
X#include "../net/route.h"
X#include "protosw.h"
X
X#include "ns.h"
X#include "ns_if.h"
X#include "ns_pcb.h"
X
Xstruct ns_addr zerons_addr;
X
Xns_pcballoc(so, head)
X struct socket *so;
X struct nspcb *head;
X{
X struct mbuf *m;
X register struct nspcb *nsp;
X
X m = m_getclr(M_DONTWAIT, MT_PCB);
X if (m == NULL)
X return (ENOBUFS);
X nsp = mtod(m, struct nspcb *);
X nsp->nsp_socket = so;
X insque(nsp, head);
X so->so_pcb = (caddr_t)nsp;
X return (0);
X}
X
Xns_pcbbind(nsp, nam)
X register struct nspcb *nsp;
X struct mbuf *nam;
X{
X register struct sockaddr_ns *sns;
X u_short lport = 0;
X
X if(nsp->nsp_lport || !ns_nullhost(nsp->nsp_laddr))
X return (EINVAL);
X if (nam == 0)
X goto noname;
X sns = mtod(nam, struct sockaddr_ns *);
X if (nam->m_len != sizeof (*sns))
X return (EINVAL);
X if (!ns_nullhost(sns->sns_addr)) {
X int tport = sns->sns_port;
X
X sns->sns_port = 0; /* yech... */
X if (ifa_ifwithaddr((struct sockaddr *)sns) == 0)
X return (EADDRNOTAVAIL);
X sns->sns_port = tport;
X }
X lport = sns->sns_port;
X if (lport) {
X u_short aport = ntohs(lport);
X
X if (aport < NSPORT_RESERVED && u.u_uid != 0)
X return (EACCES);
X if (ns_pcblookup(&zerons_addr, lport, 0))
X return (EADDRINUSE);
X }
X nsp->nsp_laddr = sns->sns_addr;
Xnoname:
X if (lport == 0)
X do {
X if (nspcb.nsp_lport++ < NSPORT_RESERVED)
X nspcb.nsp_lport = NSPORT_RESERVED;
X lport = htons(nspcb.nsp_lport);
X } while (ns_pcblookup(&zerons_addr, lport, 0));
X nsp->nsp_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 sns.
X * If don't have a local address for this socket yet,
X * then pick one.
X */
Xns_pcbconnect(nsp, nam)
X struct nspcb *nsp;
X struct mbuf *nam;
X{
X struct ns_ifaddr *ia;
X register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
X struct sockaddr_ns *ifaddr;
X register struct ns_addr *dst;
X
X if (nam->m_len != sizeof (*sns))
X return (EINVAL);
X if (sns->sns_family != AF_NS)
X return (EAFNOSUPPORT);
X if (sns->sns_port==0 || ns_nullhost(sns->sns_addr))
X return (EADDRNOTAVAIL);
X if (ns_nullhost(nsp->nsp_laddr)) {
X register struct route *ro;
X struct ifnet *ifp;
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 = &nsp->nsp_route;
X dst = &satons_addr(ro->ro_dst);
X
X ia = (struct ns_ifaddr *)0;
X if (ro->ro_rt) {
X if ((!ns_neteq(nsp->nsp_lastdst, sns->sns_addr)) ||
X ((ifp = ro->ro_rt->rt_ifp) &&
X (ifp->if_flags & IFF_POINTOPOINT) &&
X (!ns_hosteq(nsp->nsp_lastdst, sns->sns_addr))) ||
X (nsp->nsp_socket->so_options & SO_DONTROUTE)) {
X RTFREE(ro->ro_rt);
X ro->ro_rt = (struct rtentry *)0;
X }
X }
X if ((nsp->nsp_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_NS;
X *dst = sns->sns_addr;
X dst->x_port = 0;
X rtalloc(ro);
X }
X /*
X * If we found a route, use the address
X * corresponding to the outgoing interface
X */
X if (ro->ro_rt && (ifp = ro->ro_rt->rt_ifp))
X for (ia = ns_ifaddr; ia; ia = ia->ia_next)
X if (ia->ia_ifp == ifp)
X break;
X if (ia == 0) {
X u_short fport = sns->sns_addr.x_port;
X sns->sns_addr.x_port = 0;
X ia = (struct ns_ifaddr *)
X ifa_ifwithdstaddr((struct sockaddr *)sns);
X sns->sns_addr.x_port = fport;
X if (ia == 0)
X ia = ns_iaonnetof(&sns->sns_addr);
X if (ia == 0)
X ia = ns_ifaddr;
X if (ia == 0)
X return (EADDRNOTAVAIL);
X }
X nsp->nsp_laddr.x_net = satons_addr(ia->ia_addr).x_net;
X nsp->nsp_lastdst = sns->sns_addr;
X }
X if (ns_pcblookup(&sns->sns_addr, nsp->nsp_lport, 0))
X return (EADDRINUSE);
X if (ns_nullhost(nsp->nsp_laddr)) {
X if (nsp->nsp_lport == 0)
X (void) ns_pcbbind(nsp, (struct mbuf *)0);
X nsp->nsp_laddr.x_host = ns_thishost;
X }
X nsp->nsp_faddr = sns->sns_addr;
X /* Includes nsp->nsp_fport = sns->sns_port; */
X return (0);
X}
X
Xns_pcbdisconnect(nsp)
X struct nspcb *nsp;
X{
X
X nsp->nsp_faddr = zerons_addr;
X if (nsp->nsp_socket->so_state & SS_NOFDREF)
X ns_pcbdetach(nsp);
X}
X
Xns_pcbdetach(nsp)
X struct nspcb *nsp;
X{
X struct socket *so = nsp->nsp_socket;
X
X so->so_pcb = 0;
X sofree(so);
X if (nsp->nsp_route.ro_rt)
X rtfree(nsp->nsp_route.ro_rt);
X remque(nsp);
X (void) m_free(dtom(nsp));
X}
X
Xns_setsockaddr(nsp, nam)
X register struct nspcb *nsp;
X struct mbuf *nam;
X{
X register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
X
X nam->m_len = sizeof (*sns);
X sns = mtod(nam, struct sockaddr_ns *);
X bzero((caddr_t)sns, sizeof (*sns));
X sns->sns_family = AF_NS;
X sns->sns_addr = nsp->nsp_laddr;
X}
X
Xns_setpeeraddr(nsp, nam)
X register struct nspcb *nsp;
X struct mbuf *nam;
X{
X register struct sockaddr_ns *sns = mtod(nam, struct sockaddr_ns *);
X
X nam->m_len = sizeof (*sns);
X sns = mtod(nam, struct sockaddr_ns *);
X bzero((caddr_t)sns, sizeof (*sns));
X sns->sns_family = AF_NS;
X sns->sns_addr = nsp->nsp_faddr;
X}
X
X/*
X * Pass some notification to all connections of a protocol
X * associated with address dst. Call the
X * protocol specific routine to handle each connection.
X * Also pass an extra paramter via the nspcb. (which may in fact
X * be a parameter list!)
X */
Xns_pcbnotify(dst, errno, notify, param)
X register struct ns_addr *dst;
X long param;
X int errno, (*notify)();
X{
X register struct nspcb *nsp, *oinp;
X int s = splimp();
X
X for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb);) {
X if (!ns_hosteq(*dst,nsp->nsp_faddr)) {
X next:
X nsp = nsp->nsp_next;
X continue;
X }
X if (nsp->nsp_socket == 0)
X goto next;
X if (errno)
X nsp->nsp_socket->so_error = errno;
X oinp = nsp;
X nsp = nsp->nsp_next;
X oinp->nsp_notify_param = param;
X (*notify)(oinp);
X }
X splx(s);
X}
X
X#ifdef notdef
X/*
X * After a routing change, flush old routing
X * and allocate a (hopefully) better one.
X */
Xns_rtchange(nsp)
X struct nspcb *nsp;
X{
X if (nsp->nsp_route.ro_rt) {
X rtfree(nsp->nsp_route.ro_rt);
X nsp->nsp_route.ro_rt = 0;
X /*
X * A new route can be allocated the next time
X * output is attempted.
X */
X }
X /* SHOULD NOTIFY HIGHER-LEVEL PROTOCOLS */
X}
X#endif
X
Xstruct nspcb *
Xns_pcblookup(faddr, lport, wildp)
X struct ns_addr *faddr;
X u_short lport;
X{
X register struct nspcb *nsp, *match = 0;
X int matchwild = 3, wildcard;
X u_short fport;
X
X fport = faddr->x_port;
X for (nsp = (&nspcb)->nsp_next; nsp != (&nspcb); nsp = nsp->nsp_next) {
X if (nsp->nsp_lport != lport)
X continue;
X wildcard = 0;
X if (ns_nullhost(nsp->nsp_faddr)) {
X if (!ns_nullhost(*faddr))
X wildcard++;
X } else {
X if (ns_nullhost(*faddr))
X wildcard++;
X else {
X if (!ns_hosteq(nsp->nsp_faddr, *faddr))
X continue;
X if( nsp->nsp_fport != fport) {
X if(nsp->nsp_fport != 0)
X continue;
X else
X wildcard++;
X }
X }
X }
X if (wildcard && wildp==0)
X continue;
X if (wildcard < matchwild) {
X match = nsp;
X matchwild = wildcard;
X if (wildcard == 0)
X break;
X }
X }
X return (match);
X}
END-of-netns/ns_pcb.c
echo x - netns/ns_pcb.h
sed 's/^X//' >netns/ns_pcb.h << 'END-of-netns/ns_pcb.h'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns_pcb.h 7.2 (Berkeley) 1/20/88
X */
X
X/*
X * Ns protocol interface control block.
X */
Xstruct nspcb {
X struct nspcb *nsp_next; /* doubly linked list */
X struct nspcb *nsp_prev;
X struct nspcb *nsp_head;
X struct socket *nsp_socket; /* back pointer to socket */
X struct ns_addr nsp_faddr; /* destination address */
X struct ns_addr nsp_laddr; /* socket's address */
X caddr_t nsp_pcb; /* protocol specific stuff */
X struct route nsp_route; /* routing information */
X struct ns_addr nsp_lastdst; /* validate cached route for dg socks*/
X long nsp_notify_param; /* extra info passed via ns_pcbnotify*/
X short nsp_flags;
X u_char nsp_dpt; /* default packet type for idp_output*/
X u_char nsp_rpt; /* last received packet type by
X idp_input() */
X};
X
X/* possible flags */
X
X#define NSP_IN_ABORT 0x1 /* calling abort through socket */
X#define NSP_RAWIN 0x2 /* show headers on input */
X#define NSP_RAWOUT 0x4 /* show header on output */
X#define NSP_ALL_PACKETS 0x8 /* Turn off higher proto processing */
X
X#define NS_WILDCARD 1
X
X#define nsp_lport nsp_laddr.x_port
X#define nsp_fport nsp_faddr.x_port
X
X#define sotonspcb(so) ((struct nspcb *)((so)->so_pcb))
X
X/*
X * Nominal space allocated to a ns socket.
X */
X#define NSSNDQ 2048
X#define NSRCVQ 2048
X
X
X#ifdef KERNEL
Xstruct nspcb nspcb; /* head of list */
Xstruct nspcb *ns_pcblookup();
X#endif
END-of-netns/ns_pcb.h
echo x - netns/ns_proto.c
sed 's/^X//' >netns/ns_proto.c << 'END-of-netns/ns_proto.c'
X/*
X * Copyright (c) 1984, 1985, 1986, 1987 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 * @(#)ns_proto.c 7.2 (Berkeley) 1/20/88
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 "ns.h"
X
X/*
X * NS protocol family: IDP, ERR, PE, SPP, ROUTE.
X */
Xint ns_init();
Xint idp_input(), idp_output(), idp_ctlinput(), idp_usrreq();
Xint idp_raw_usrreq(), idp_ctloutput();
Xint spp_input(), spp_ctlinput();
Xint spp_usrreq(), spp_usrreq_sp(), spp_ctloutput();
Xint spp_init(), spp_fasttimo(), spp_slowtimo();
Xextern int raw_usrreq();
X
Xextern struct domain nsdomain;
X
Xstruct protosw nssw[] = {
X{ 0, &nsdomain, 0, 0,
X 0, idp_output, 0, 0,
X 0,
X ns_init, 0, 0, 0,
X},
X{ SOCK_DGRAM, &nsdomain, 0, PR_ATOMIC|PR_ADDR,
X 0, 0, idp_ctlinput, idp_ctloutput,
X idp_usrreq,
X 0, 0, 0, 0,
X},
X{ SOCK_STREAM, &nsdomain, NSPROTO_SPP, PR_CONNREQUIRED|PR_WANTRCVD,
X spp_input, 0, spp_ctlinput, spp_ctloutput,
X spp_usrreq,
X spp_init, spp_fasttimo, spp_slowtimo, 0,
X},
X{ SOCK_SEQPACKET,&nsdomain, NSPROTO_SPP, PR_CONNREQUIRED|PR_WANTRCVD|PR_ATOMIC,
X spp_input, 0, spp_ctlinput, spp_ctloutput,
X spp_usrreq_sp,
X 0, 0, 0, 0,
X},
X{ SOCK_RAW, &nsdomain, NSPROTO_RAW, PR_ATOMIC|PR_ADDR,
X idp_input, idp_output, 0, idp_ctloutput,
X idp_raw_usrreq,
X 0, 0, 0, 0,
X},
X{ SOCK_RAW, &nsdomain, NSPROTO_ERROR, PR_ATOMIC|PR_ADDR,
X idp_ctlinput, idp_output, 0, idp_ctloutput,
X idp_raw_usrreq,
X 0, 0, 0, 0,
X},
X};
X
Xstruct domain nsdomain =
X { AF_NS, "network systems", 0, 0, 0,
X nssw, &nssw[sizeof(nssw)/sizeof(nssw[0])] };
X
END-of-netns/ns_proto.c
exit
More information about the Comp.bugs.4bsd.ucb-fixes
mailing list