X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/bbcda6f4379ea3f61eaf6e85e6f9267a1754f57f..a2cdf9f6b08eceef2637b965669f0e87065b27fb:/usr/src/sys/netns/ns_input.c diff --git a/usr/src/sys/netns/ns_input.c b/usr/src/sys/netns/ns_input.c index 320036d37b..32a84cf186 100644 --- a/usr/src/sys/netns/ns_input.c +++ b/usr/src/sys/netns/ns_input.c @@ -1,26 +1,34 @@ -/* ns_input.c 6.1 85/05/30 */ - -#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" +/* + * Copyright (c) 1984, 1985, 1986, 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * %sccs.include.redist.c% + * + * @(#)ns_input.c 8.1 (Berkeley) %G% + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include /* * NS initialization. @@ -28,8 +36,11 @@ 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; @@ -37,14 +48,24 @@ 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; } /* @@ -56,8 +77,7 @@ nsintr() { 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; @@ -73,7 +93,7 @@ next: 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; @@ -83,7 +103,7 @@ 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); } @@ -100,30 +120,22 @@ next: * 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 @@ -136,60 +148,57 @@ next: * 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 as well. + * Look to see if I need to eat this packet. + * Algorithm is to forward all young packets + * and prematurely age any packets which will + * by physically broadcasted. + * Any very old packets eaten without forwarding + * would die anyway. + * + * Suggestion of Bill Nesheim, Cornell U. */ - struct ns_ifaddr *ia = - ns_iaonnetof(idp->idp_dna.x_net); - if (ia) { - m = m_copy(m, 0, M_COPYALL); - } else - m = NULL; - idp_forward(idp); - if (m==NULL) + if (idp->idp_tc < NS_MAXHOPS) { + idp_forward(m); goto next; - idp = mtod(m, struct idp *); + } } /* * 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; @@ -207,12 +216,17 @@ u_char nsctlerrmap[PRC_NCMDS] = { 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) @@ -220,19 +234,35 @@ idp_ctlinput(cmd, arg) 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]); } } @@ -247,11 +277,16 @@ int idpforwarding = 1; 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 *mopt, *mcopy; + struct mbuf *mcopy = NULL; + int agedelta = 1; + int flags = NS_FORWARDING; + int ok_there = 0; + int ok_back = 0; if (idpprintfs) { printf("forward: src "); @@ -270,6 +305,46 @@ idp_forward(idp) type = NS_ERR_TOO_OLD, code = 0; goto senderror; } + /* + * Save at most 42 bytes of the packet in case + * we need to generate an NS error message to the src. + */ + mcopy = m_copy(m, 0, imin((int)ntohs(idp->idp_len), 42)); + + if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) { + type = NS_ERR_UNREACH_HOST, code = 0; + goto senderror; + } + /* + * Here we think about forwarding broadcast packets, + * so we try to insure that it doesn't go back out + * on the interface it came in on. Also, if we + * are going to physically broadcast this, let us + * 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); + struct ifnet *ifp; + if (ia) { + /* I'm gonna hafta eat this packet */ + agedelta += NS_MAXHOPS - idp->idp_tc; + idp->idp_tc = NS_MAXHOPS; + } + if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) { + /* error = ENETUNREACH; He'll never get it! */ + m_freem(m); + goto cleanup; + } + if (idp_droute.ro_rt && + (ifp=idp_droute.ro_rt->rt_ifp) && + idp_sroute.ro_rt && + (ifp!=idp_sroute.ro_rt->rt_ifp)) { + flags |= NS_ALLOWBROADCAST; + } else { + type = NS_ERR_UNREACH_HOST, code = 0; + goto senderror; + } + } /* need to adjust checksum */ if (idp->idp_sum!=0xffff) { union bytes { @@ -278,78 +353,47 @@ idp_forward(idp) long l; } x; register int shift; - x.l = 0; x.c[0] = 1; + 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; } - mopt = m_get(M_DONTWAIT, MT_DATA); - if (mopt == NULL) { - m_freem(dtom(idp)); - return; - } + if ((error = ns_output(m, &idp_droute, flags)) && + (mcopy!=NULL)) { + idp = mtod(mcopy, struct idp *); + type = NS_ERR_UNSPEC_T, code = 0; + switch (error) { + + case ENETUNREACH: + case EHOSTDOWN: + case EHOSTUNREACH: + case ENETDOWN: + case EPERM: + type = NS_ERR_UNREACH_HOST; + break; - /* - * 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)); + case EMSGSIZE: + type = NS_ERR_TOO_BIG; + code = 576; /* too hard to figure out mtu here */ + break; - if ((idp->idp_dna.x_host.c_host[0] & 0x1) == 0) - error = ns_output(dtom(idp), (struct route *)0, NS_FORWARDING); - /* - * Here we are about to forward a broadcast packet, - * so we try to insure that it doesn't go back out - * on the interface it came in on. - */ - else if (idp_do_route(&idp->idp_dna,&idp_droute)) { - if (idp_do_route(&idp->idp_sna,&idp_sroute)) { - struct ifnet *ifp; - - if (idp_droute.ro_rt && - (ifp=idp_droute.ro_rt->rt_ifp) && - idp_sroute.ro_rt && - (ifp!=idp_sroute.ro_rt->rt_ifp)) { - error = ns_output(dtom(idp), &idp_droute, - NS_FORWARDING|NS_ALLOWBROADCAST); - } - idp_undo_route(&idp_sroute); + case ENOBUFS: + type = NS_ERR_UNSPEC_T; + break; } - idp_undo_route(&idp_droute); - } - - if (error == 0) { - if (mcopy) - m_freem(mcopy); - return; - } - if (mcopy == NULL) - return; - idp = mtod(mcopy, struct idp *); - type = NS_ERR_UNSPEC_T, code = 0; - switch (error) { - - case ENETUNREACH: - case EHOSTDOWN: - case EHOSTUNREACH: - case ENETDOWN: - case EPERM: - type = NS_ERR_UNREACH_HOST; - break; - - case EMSGSIZE: - type = NS_ERR_TOO_BIG; - code = 576; /* too hard to figure out mtu here */ - break; - - case ENOBUFS: - type = NS_ERR_UNSPEC_T; - break; + mcopy = NULL; + senderror: + ns_error(m, type, code); } -senderror: - ns_error(dtom(idp), type, code); +cleanup: + if (ok_there) + idp_undo_route(&idp_droute); + if (ok_back) + idp_undo_route(&idp_sroute); + if (mcopy != NULL) + m_freem(mcopy); } idp_do_route(src, ro) @@ -362,14 +406,16 @@ struct route *ro; 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) @@ -377,15 +423,37 @@ register struct 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); + } } }