/*
- * Copyright (c) 1982 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1984, 1985, 1986, 1987, 1993
+ * The Regents of the University of California. All rights reserved.
*
- * @(#)ns_input.c 6.3 (Berkeley) %G%
+ * %sccs.include.redist.c%
+ *
+ * @(#)ns_input.c 8.1 (Berkeley) %G%
*/
-#include "param.h"
-#include "systm.h"
-#include "mbuf.h"
-#include "domain.h"
-#include "protosw.h"
-#include "socket.h"
-#include "socketvar.h"
-#include "errno.h"
-#include "time.h"
-#include "kernel.h"
-
-#include "../net/if.h"
-#include "../net/route.h"
-#include "../net/raw_cb.h"
-
-#include "ns.h"
-#include "ns_if.h"
-#include "ns_pcb.h"
-#include "idp.h"
-#include "idp_var.h"
-#include "ns_error.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/raw_cb.h>
+
+#include <netns/ns.h>
+#include <netns/ns_if.h>
+#include <netns/ns_pcb.h>
+#include <netns/idp.h>
+#include <netns/idp_var.h>
+#include <netns/ns_error.h>
/*
* NS initialization.
union ns_host ns_thishost;
union ns_host ns_zerohost;
union ns_host ns_broadhost;
+union ns_net ns_zeronet;
+union ns_net ns_broadnet;
+struct sockaddr_ns ns_netmask, ns_hostmask;
-static char allones[] = {-1, -1, -1, -1, -1, -1};
+static u_short allones[] = {-1, -1, -1};
struct nspcb nspcb;
struct nspcb nsrawpcb;
struct ifqueue nsintrq;
int nsqmaxlen = IFQ_MAXLEN;
-int idpcksum = 0;
+int idpcksum = 1;
+long ns_pexseq;
ns_init()
{
+ extern struct timeval time;
+
ns_broadhost = * (union ns_host *) allones;
+ ns_broadnet = * (union ns_net *) allones;
nspcb.nsp_next = nspcb.nsp_prev = &nspcb;
nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb;
nsintrq.ifq_maxlen = nsqmaxlen;
+ ns_pexseq = time.tv_usec;
+ ns_netmask.sns_len = 6;
+ ns_netmask.sns_addr.x_net = ns_broadnet;
+ ns_hostmask.sns_len = 12;
+ ns_hostmask.sns_addr.x_net = ns_broadnet;
+ ns_hostmask.sns_addr.x_host = ns_broadhost;
}
/*
{
register struct idp *idp;
register struct mbuf *m;
- struct nspcb *nsp;
- struct mbuf *m0;
+ register struct nspcb *nsp;
register int i;
int len, s, error;
char oddpacketp;
nsintr_getpck++;
if (m == 0)
return;
- if ((m->m_off > MMAXOFF || m->m_len < sizeof (struct idp)) &&
+ if ((m->m_flags & M_EXT || m->m_len < sizeof (struct idp)) &&
(m = m_pullup(m, sizeof (struct idp))) == 0) {
idpstat.idps_toosmall++;
goto next;
* Give any raw listeners a crack at the packet
*/
for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
- struct mbuf *m1 = m_copy(m, 0, M_COPYALL);
+ struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL);
if (m1) idp_input(m1, nsp);
}
* Trim mbufs if longer than we expect.
* Drop packet if shorter than we expect.
*/
- i = -len;
- m0 = m;
- for (;;) {
- i += m->m_len;
- if (m->m_next == 0)
- break;
- m = m->m_next;
+ if (m->m_pkthdr.len < len) {
+ idpstat.idps_tooshort++;
+ goto bad;
}
- if (i != 0) {
- if (i < 0) {
- idpstat.idps_tooshort++;
- m = m0;
- goto bad;
- }
- if (i <= m->m_len)
- m->m_len -= i;
- else
- m_adj(m0, -i);
+ if (m->m_pkthdr.len > len) {
+ if (m->m_len == m->m_pkthdr.len) {
+ m->m_len = len;
+ m->m_pkthdr.len = len;
+ } else
+ m_adj(m, len - m->m_pkthdr.len);
}
- m = m0;
if (idpcksum && ((i = idp->idp_sum)!=0xffff)) {
idp->idp_sum = 0;
- if (i != (idp->idp_sum = ns_cksum(m,len))) {
+ if (i != (idp->idp_sum = ns_cksum(m, len))) {
idpstat.idps_badsum++;
+ idp->idp_sum = i;
if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host))
error = NS_ERR_BADSUM;
else
* Is this a directed broadcast?
*/
if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) {
- if ((ns_netof(idp->idp_dna)!=ns_netof(idp->idp_sna)) &&
- (ns_netof(idp->idp_dna)!=-1) && (ns_netof(idp->idp_sna)!=0)
- && (ns_netof(idp->idp_dna)!=0)) {
+ if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) &&
+ (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) &&
+ (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) &&
+ (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) {
/*
* Look to see if I need to eat this packet.
* Algorithm is to forward all young packets
*
* Suggestion of Bill Nesheim, Cornell U.
*/
- if(idp->idp_tc < NS_MAXHOPS) {
- idp_forward(idp);
+ if (idp->idp_tc < NS_MAXHOPS) {
+ idp_forward(m);
goto next;
}
}
* Is this our packet? If not, forward.
*/
} else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) {
- idp_forward(idp);
+ idp_forward(m);
goto next;
}
-
/*
* Locate pcb for datagram.
*/
nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD);
-
-
- /*
- * Switch out to protocol's input routine.
- */
-
+ /*
+ * Switch out to protocol's input routine.
+ */
nsintr_swtch++;
if (nsp) {
if (oddpacketp) {
- m_adj(m0, -1);
- }
- switch (idp->idp_pt) {
- case NSPROTO_SPP:
- spp_input(m,nsp);
- break;
- case NSPROTO_ERROR:
- ns_err_input(m);
- break;
- default:
- idp_input(m,nsp);
+ m_adj(m, -1);
}
+ if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0)
+ switch (idp->idp_pt) {
+
+ case NSPROTO_SPP:
+ spp_input(m, nsp);
+ goto next;
+
+ case NSPROTO_ERROR:
+ ns_err_input(m);
+ goto next;
+ }
+ idp_input(m, nsp);
} else {
- /* don't send ERROR response for multicast packet */
- if (idp->idp_dna.x_host.c_host[0] & 1)
- goto bad;
ns_error(m, NS_ERR_NOSOCK, 0);
}
goto next;
0, 0, 0, 0
};
+int idp_donosocks = 1;
+
idp_ctlinput(cmd, arg)
int cmd;
caddr_t arg;
{
struct ns_addr *ns;
+ struct nspcb *nsp;
+ struct ns_errp *errp;
int idp_abort();
+ extern struct nspcb *idp_drop();
int type;
if (cmd < 0 || cmd > PRC_NCMDS)
if (nsctlerrmap[cmd] == 0)
return; /* XXX */
type = NS_ERR_UNREACH_HOST;
- if (cmd == PRC_IFDOWN)
- ns = &((struct sockaddr_ns *)arg)->sns_addr;
- else if (cmd == PRC_HOSTDEAD || cmd == PRC_HOSTUNREACH)
- ns = (struct ns_addr *)arg;
- else {
- ns = &((struct ns_errp *)arg)->ns_err_idp.idp_dna;
- type = ((struct ns_errp *)arg)->ns_err_num;
- type = ntohs(type);
+ switch (cmd) {
+ struct sockaddr_ns *sns;
+
+ case PRC_IFDOWN:
+ case PRC_HOSTDEAD:
+ case PRC_HOSTUNREACH:
+ sns = (struct sockaddr_ns *)arg;
+ if (sns->sns_family != AF_NS)
+ return;
+ ns = &sns->sns_addr;
+ break;
+
+ default:
+ errp = (struct ns_errp *)arg;
+ ns = &errp->ns_err_idp.idp_dna;
+ type = errp->ns_err_num;
+ type = ntohs((u_short)type);
}
switch (type) {
+
case NS_ERR_UNREACH_HOST:
+ ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0);
+ break;
+
case NS_ERR_NOSOCK:
- ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, 0);
+ nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port,
+ NS_WILDCARD);
+ if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr))
+ (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
}
}
struct route idp_droute;
struct route idp_sroute;
-idp_forward(idp)
- register struct idp *idp;
+idp_forward(m)
+struct mbuf *m;
{
+ register struct idp *idp = mtod(m, struct idp *);
register int error, type, code;
struct mbuf *mcopy = NULL;
int agedelta = 1;
* Save at most 42 bytes of the packet in case
* we need to generate an NS error message to the src.
*/
- mcopy = m_copy(dtom(idp), 0, imin(ntohs(idp->idp_len), 42));
+ mcopy = m_copy(m, 0, imin((int)ntohs(idp->idp_len), 42));
- if((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) {
+ if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) {
type = NS_ERR_UNREACH_HOST, code = 0;
goto senderror;
}
* age the packet so we can eat it safely the second time around.
*/
if (idp->idp_dna.x_host.c_host[0] & 0x1) {
- struct ns_ifaddr *ia = ns_iaonnetof(idp->idp_dna.x_net);
+ struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
struct ifnet *ifp;
if (ia) {
/* I'm gonna hafta eat this packet */
}
if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) {
/* error = ENETUNREACH; He'll never get it! */
- m_freem(dtom(idp));
+ m_freem(m);
goto cleanup;
}
if (idp_droute.ro_rt &&
register int shift;
x.l = 0; x.c[0] = agedelta;
shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf;
- x.l = idp->idp_sum + (x.l << shift);
+ x.l = idp->idp_sum + (x.s[0] << shift);
x.l = x.s[0] + x.s[1];
x.l = x.s[0] + x.s[1];
if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l;
}
- if ((error = ns_output(dtom(idp), &idp_droute, flags)) &&
+ if ((error = ns_output(m, &idp_droute, flags)) &&
(mcopy!=NULL)) {
idp = mtod(mcopy, struct idp *);
type = NS_ERR_UNSPEC_T, code = 0;
type = NS_ERR_UNSPEC_T;
break;
}
+ mcopy = NULL;
+ senderror:
+ ns_error(m, type, code);
}
-senderror:
- ns_error(dtom(idp), type, code);
- mcopy = NULL;
cleanup:
if (ok_there)
idp_undo_route(&idp_droute);
bzero((caddr_t)ro, sizeof (*ro));
dst = (struct sockaddr_ns *)&ro->ro_dst;
+ dst->sns_len = sizeof(*dst);
dst->sns_family = AF_NS;
dst->sns_addr = *src;
+ dst->sns_addr.x_port = 0;
rtalloc(ro);
if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) {
- return(0);
+ return (0);
}
ro->ro_rt->rt_use++;
- return(1);
+ return (1);
}
idp_undo_route(ro)
{
if (ro->ro_rt) {RTFREE(ro->ro_rt);}
}
-ns_watch_output(m)
+
+ns_watch_output(m, ifp)
struct mbuf *m;
+struct ifnet *ifp;
{
register struct nspcb *nsp;
+ register struct ifaddr *ifa;
/*
* Give any raw listeners a crack at the packet
*/
for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
- struct mbuf *m1 = m_copy(m, 0, M_COPYALL);
- if (m1) idp_input(m1, nsp);
+ struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL);
+ if (m0) {
+ register struct idp *idp;
+
+ M_PREPEND(m0, sizeof (*idp), M_DONTWAIT);
+ if (m0 == NULL)
+ continue;
+ idp = mtod(m0, struct idp *);
+ idp->idp_sna.x_net = ns_zeronet;
+ idp->idp_sna.x_host = ns_thishost;
+ if (ifp && (ifp->if_flags & IFF_POINTOPOINT))
+ for(ifa = ifp->if_addrlist; ifa;
+ ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family==AF_NS) {
+ idp->idp_sna = IA_SNS(ifa)->sns_addr;
+ break;
+ }
+ }
+ idp->idp_len = ntohl(m0->m_pkthdr.len);
+ idp_input(m0, nsp);
+ }
}
}