bostic@OKEEFFE.BERKELEY.EDU (Keith Bostic) (04/05/88)
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