home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netns / ns_input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-27  |  11.8 KB  |  486 lines

  1. /*
  2.  * Copyright (c) 1984, 1985, 1986, 1987 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  *
  33.  *    @(#)ns_input.c    7.8 (Berkeley) 6/27/91
  34.  */
  35.  
  36. #include "param.h"
  37. #include "systm.h"
  38. #include "malloc.h"
  39. #include "mbuf.h"
  40. #include "domain.h"
  41. #include "protosw.h"
  42. #include "socket.h"
  43. #include "socketvar.h"
  44. #include "errno.h"
  45. #include "time.h"
  46. #include "kernel.h"
  47.  
  48. #include "../net/if.h"
  49. #include "../net/route.h"
  50. #include "../net/raw_cb.h"
  51.  
  52. #include "ns.h"
  53. #include "ns_if.h"
  54. #include "ns_pcb.h"
  55. #include "idp.h"
  56. #include "idp_var.h"
  57. #include "ns_error.h"
  58.  
  59. /*
  60.  * NS initialization.
  61.  */
  62. union ns_host    ns_thishost;
  63. union ns_host    ns_zerohost;
  64. union ns_host    ns_broadhost;
  65. union ns_net    ns_zeronet;
  66. union ns_net    ns_broadnet;
  67. struct sockaddr_ns ns_netmask, ns_hostmask;
  68.  
  69. static u_short allones[] = {-1, -1, -1};
  70.  
  71. struct nspcb nspcb;
  72. struct nspcb nsrawpcb;
  73.  
  74. struct ifqueue    nsintrq;
  75. int    nsqmaxlen = IFQ_MAXLEN;
  76.  
  77. int    idpcksum = 1;
  78. long    ns_pexseq;
  79.  
  80. ns_init()
  81. {
  82.     extern struct timeval time;
  83.  
  84.     ns_broadhost = * (union ns_host *) allones;
  85.     ns_broadnet = * (union ns_net *) allones;
  86.     nspcb.nsp_next = nspcb.nsp_prev = &nspcb;
  87.     nsrawpcb.nsp_next = nsrawpcb.nsp_prev = &nsrawpcb;
  88.     nsintrq.ifq_maxlen = nsqmaxlen;
  89.     ns_pexseq = time.tv_usec;
  90.     ns_netmask.sns_len = 6;
  91.     ns_netmask.sns_addr.x_net = ns_broadnet;
  92.     ns_hostmask.sns_len = 12;
  93.     ns_hostmask.sns_addr.x_net = ns_broadnet;
  94.     ns_hostmask.sns_addr.x_host = ns_broadhost;
  95. }
  96.  
  97. /*
  98.  * Idp input routine.  Pass to next level.
  99.  */
  100. int nsintr_getpck = 0;
  101. int nsintr_swtch = 0;
  102. nsintr()
  103. {
  104.     register struct idp *idp;
  105.     register struct mbuf *m;
  106.     register struct nspcb *nsp;
  107.     register int i;
  108.     int len, s, error;
  109.     char oddpacketp;
  110.  
  111. next:
  112.     /*
  113.      * Get next datagram off input queue and get IDP header
  114.      * in first mbuf.
  115.      */
  116.     s = splimp();
  117.     IF_DEQUEUE(&nsintrq, m);
  118.     splx(s);
  119.     nsintr_getpck++;
  120.     if (m == 0)
  121.         return;
  122.     if ((m->m_flags & M_EXT || m->m_len < sizeof (struct idp)) &&
  123.         (m = m_pullup(m, sizeof (struct idp))) == 0) {
  124.         idpstat.idps_toosmall++;
  125.         goto next;
  126.     }
  127.  
  128.     /*
  129.      * Give any raw listeners a crack at the packet
  130.      */
  131.     for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
  132.         struct mbuf *m1 = m_copy(m, 0, (int)M_COPYALL);
  133.         if (m1) idp_input(m1, nsp);
  134.     }
  135.  
  136.     idp = mtod(m, struct idp *);
  137.     len = ntohs(idp->idp_len);
  138.     if (oddpacketp = len & 1) {
  139.         len++;        /* If this packet is of odd length,
  140.                    preserve garbage byte for checksum */
  141.     }
  142.  
  143.     /*
  144.      * Check that the amount of data in the buffers
  145.      * is as at least much as the IDP header would have us expect.
  146.      * Trim mbufs if longer than we expect.
  147.      * Drop packet if shorter than we expect.
  148.      */
  149.     if (m->m_pkthdr.len < len) {
  150.         idpstat.idps_tooshort++;
  151.         goto bad;
  152.     }
  153.     if (m->m_pkthdr.len > len) {
  154.         if (m->m_len == m->m_pkthdr.len) {
  155.             m->m_len = len;
  156.             m->m_pkthdr.len = len;
  157.         } else
  158.             m_adj(m, len - m->m_pkthdr.len);
  159.     }
  160.     if (idpcksum && ((i = idp->idp_sum)!=0xffff)) {
  161.         idp->idp_sum = 0;
  162.         if (i != (idp->idp_sum = ns_cksum(m, len))) {
  163.             idpstat.idps_badsum++;
  164.             idp->idp_sum = i;
  165.             if (ns_hosteqnh(ns_thishost, idp->idp_dna.x_host))
  166.                 error = NS_ERR_BADSUM;
  167.             else
  168.                 error = NS_ERR_BADSUM_T;
  169.             ns_error(m, error, 0);
  170.             goto next;
  171.         }
  172.     }
  173.     /*
  174.      * Is this a directed broadcast?
  175.      */
  176.     if (ns_hosteqnh(ns_broadhost,idp->idp_dna.x_host)) {
  177.         if ((!ns_neteq(idp->idp_dna, idp->idp_sna)) &&
  178.             (!ns_neteqnn(idp->idp_dna.x_net, ns_broadnet)) &&
  179.             (!ns_neteqnn(idp->idp_sna.x_net, ns_zeronet)) &&
  180.             (!ns_neteqnn(idp->idp_dna.x_net, ns_zeronet)) ) {
  181.             /*
  182.              * Look to see if I need to eat this packet.
  183.              * Algorithm is to forward all young packets
  184.              * and prematurely age any packets which will
  185.              * by physically broadcasted.
  186.              * Any very old packets eaten without forwarding
  187.              * would die anyway.
  188.              *
  189.              * Suggestion of Bill Nesheim, Cornell U.
  190.              */
  191.             if (idp->idp_tc < NS_MAXHOPS) {
  192.                 idp_forward(m);
  193.                 goto next;
  194.             }
  195.         }
  196.     /*
  197.      * Is this our packet? If not, forward.
  198.      */
  199.     } else if (!ns_hosteqnh(ns_thishost,idp->idp_dna.x_host)) {
  200.         idp_forward(m);
  201.         goto next;
  202.     }
  203.     /*
  204.      * Locate pcb for datagram.
  205.      */
  206.     nsp = ns_pcblookup(&idp->idp_sna, idp->idp_dna.x_port, NS_WILDCARD);
  207.     /*
  208.      * Switch out to protocol's input routine.
  209.      */
  210.     nsintr_swtch++;
  211.     if (nsp) {
  212.         if (oddpacketp) {
  213.             m_adj(m, -1);
  214.         }
  215.         if ((nsp->nsp_flags & NSP_ALL_PACKETS)==0)
  216.             switch (idp->idp_pt) {
  217.  
  218.                 case NSPROTO_SPP:
  219.                     spp_input(m, nsp);
  220.                     goto next;
  221.  
  222.                 case NSPROTO_ERROR:
  223.                     ns_err_input(m);
  224.                     goto next;
  225.             }
  226.         idp_input(m, nsp);
  227.     } else {
  228.         ns_error(m, NS_ERR_NOSOCK, 0);
  229.     }
  230.     goto next;
  231.  
  232. bad:
  233.     m_freem(m);
  234.     goto next;
  235. }
  236.  
  237. u_char nsctlerrmap[PRC_NCMDS] = {
  238.     ECONNABORTED,    ECONNABORTED,    0,        0,
  239.     0,        0,        EHOSTDOWN,    EHOSTUNREACH,
  240.     ENETUNREACH,    EHOSTUNREACH,    ECONNREFUSED,    ECONNREFUSED,
  241.     EMSGSIZE,    0,        0,        0,
  242.     0,        0,        0,        0
  243. };
  244.  
  245. int idp_donosocks = 1;
  246.  
  247. idp_ctlinput(cmd, arg)
  248.     int cmd;
  249.     caddr_t arg;
  250. {
  251.     struct ns_addr *ns;
  252.     struct nspcb *nsp;
  253.     struct ns_errp *errp;
  254.     int idp_abort();
  255.     extern struct nspcb *idp_drop();
  256.     int type;
  257.  
  258.     if (cmd < 0 || cmd > PRC_NCMDS)
  259.         return;
  260.     if (nsctlerrmap[cmd] == 0)
  261.         return;        /* XXX */
  262.     type = NS_ERR_UNREACH_HOST;
  263.     switch (cmd) {
  264.         struct sockaddr_ns *sns;
  265.  
  266.     case PRC_IFDOWN:
  267.     case PRC_HOSTDEAD:
  268.     case PRC_HOSTUNREACH:
  269.         sns = (struct sockaddr_ns *)arg;
  270.         if (sns->sns_family != AF_NS)
  271.             return;
  272.         ns = &sns->sns_addr;
  273.         break;
  274.  
  275.     default:
  276.         errp = (struct ns_errp *)arg;
  277.         ns = &errp->ns_err_idp.idp_dna;
  278.         type = errp->ns_err_num;
  279.         type = ntohs((u_short)type);
  280.     }
  281.     switch (type) {
  282.  
  283.     case NS_ERR_UNREACH_HOST:
  284.         ns_pcbnotify(ns, (int)nsctlerrmap[cmd], idp_abort, (long)0);
  285.         break;
  286.  
  287.     case NS_ERR_NOSOCK:
  288.         nsp = ns_pcblookup(ns, errp->ns_err_idp.idp_sna.x_port,
  289.             NS_WILDCARD);
  290.         if(nsp && idp_donosocks && ! ns_nullhost(nsp->nsp_faddr))
  291.             (void) idp_drop(nsp, (int)nsctlerrmap[cmd]);
  292.     }
  293. }
  294.  
  295. int    idpprintfs = 0;
  296. int    idpforwarding = 1;
  297. /*
  298.  * Forward a packet.  If some error occurs return the sender
  299.  * an error packet.  Note we can't always generate a meaningful
  300.  * error message because the NS errors don't have a large enough repetoire
  301.  * of codes and types.
  302.  */
  303. struct route idp_droute;
  304. struct route idp_sroute;
  305.  
  306. idp_forward(m)
  307. struct mbuf *m;
  308. {
  309.     register struct idp *idp = mtod(m, struct idp *);
  310.     register int error, type, code;
  311.     struct mbuf *mcopy = NULL;
  312.     int agedelta = 1;
  313.     int flags = NS_FORWARDING;
  314.     int ok_there = 0;
  315.     int ok_back = 0;
  316.  
  317.     if (idpprintfs) {
  318.         printf("forward: src ");
  319.         ns_printhost(&idp->idp_sna);
  320.         printf(", dst ");
  321.         ns_printhost(&idp->idp_dna);
  322.         printf("hop count %d\n", idp->idp_tc);
  323.     }
  324.     if (idpforwarding == 0) {
  325.         /* can't tell difference between net and host */
  326.         type = NS_ERR_UNREACH_HOST, code = 0;
  327.         goto senderror;
  328.     }
  329.     idp->idp_tc++;
  330.     if (idp->idp_tc > NS_MAXHOPS) {
  331.         type = NS_ERR_TOO_OLD, code = 0;
  332.         goto senderror;
  333.     }
  334.     /*
  335.      * Save at most 42 bytes of the packet in case
  336.      * we need to generate an NS error message to the src.
  337.      */
  338.     mcopy = m_copy(m, 0, imin((int)ntohs(idp->idp_len), 42));
  339.  
  340.     if ((ok_there = idp_do_route(&idp->idp_dna,&idp_droute))==0) {
  341.         type = NS_ERR_UNREACH_HOST, code = 0;
  342.         goto senderror;
  343.     }
  344.     /*
  345.      * Here we think about  forwarding  broadcast packets,
  346.      * so we try to insure that it doesn't go back out
  347.      * on the interface it came in on.  Also, if we
  348.      * are going to physically broadcast this, let us
  349.      * age the packet so we can eat it safely the second time around.
  350.      */
  351.     if (idp->idp_dna.x_host.c_host[0] & 0x1) {
  352.         struct ns_ifaddr *ia = ns_iaonnetof(&idp->idp_dna);
  353.         struct ifnet *ifp;
  354.         if (ia) {
  355.             /* I'm gonna hafta eat this packet */
  356.             agedelta += NS_MAXHOPS - idp->idp_tc;
  357.             idp->idp_tc = NS_MAXHOPS;
  358.         }
  359.         if ((ok_back = idp_do_route(&idp->idp_sna,&idp_sroute))==0) {
  360.             /* error = ENETUNREACH; He'll never get it! */
  361.             m_freem(m);
  362.             goto cleanup;
  363.         }
  364.         if (idp_droute.ro_rt &&
  365.             (ifp=idp_droute.ro_rt->rt_ifp) &&
  366.             idp_sroute.ro_rt &&
  367.             (ifp!=idp_sroute.ro_rt->rt_ifp)) {
  368.             flags |= NS_ALLOWBROADCAST;
  369.         } else {
  370.             type = NS_ERR_UNREACH_HOST, code = 0;
  371.             goto senderror;
  372.         }
  373.     }
  374.     /* need to adjust checksum */
  375.     if (idp->idp_sum!=0xffff) {
  376.         union bytes {
  377.             u_char c[4];
  378.             u_short s[2];
  379.             long l;
  380.         } x;
  381.         register int shift;
  382.         x.l = 0; x.c[0] = agedelta;
  383.         shift = (((((int)ntohs(idp->idp_len))+1)>>1)-2) & 0xf;
  384.         x.l = idp->idp_sum + (x.s[0] << shift);
  385.         x.l = x.s[0] + x.s[1];
  386.         x.l = x.s[0] + x.s[1];
  387.         if (x.l==0xffff) idp->idp_sum = 0; else idp->idp_sum = x.l;
  388.     }
  389.     if ((error = ns_output(m, &idp_droute, flags)) && 
  390.         (mcopy!=NULL)) {
  391.         idp = mtod(mcopy, struct idp *);
  392.         type = NS_ERR_UNSPEC_T, code = 0;
  393.         switch (error) {
  394.  
  395.         case ENETUNREACH:
  396.         case EHOSTDOWN:
  397.         case EHOSTUNREACH:
  398.         case ENETDOWN:
  399.         case EPERM:
  400.             type = NS_ERR_UNREACH_HOST;
  401.             break;
  402.  
  403.         case EMSGSIZE:
  404.             type = NS_ERR_TOO_BIG;
  405.             code = 576; /* too hard to figure out mtu here */
  406.             break;
  407.  
  408.         case ENOBUFS:
  409.             type = NS_ERR_UNSPEC_T;
  410.             break;
  411.         }
  412.         mcopy = NULL;
  413.     senderror:
  414.         ns_error(m, type, code);
  415.     }
  416. cleanup:
  417.     if (ok_there)
  418.         idp_undo_route(&idp_droute);
  419.     if (ok_back)
  420.         idp_undo_route(&idp_sroute);
  421.     if (mcopy != NULL)
  422.         m_freem(mcopy);
  423. }
  424.  
  425. idp_do_route(src, ro)
  426. struct ns_addr *src;
  427. struct route *ro;
  428. {
  429.     
  430.     struct sockaddr_ns *dst;
  431.  
  432.     bzero((caddr_t)ro, sizeof (*ro));
  433.     dst = (struct sockaddr_ns *)&ro->ro_dst;
  434.  
  435.     dst->sns_len = sizeof(*dst);
  436.     dst->sns_family = AF_NS;
  437.     dst->sns_addr = *src;
  438.     dst->sns_addr.x_port = 0;
  439.     rtalloc(ro);
  440.     if (ro->ro_rt == 0 || ro->ro_rt->rt_ifp == 0) {
  441.         return (0);
  442.     }
  443.     ro->ro_rt->rt_use++;
  444.     return (1);
  445. }
  446.  
  447. idp_undo_route(ro)
  448. register struct route *ro;
  449. {
  450.     if (ro->ro_rt) {RTFREE(ro->ro_rt);}
  451. }
  452.  
  453. ns_watch_output(m, ifp)
  454. struct mbuf *m;
  455. struct ifnet *ifp;
  456. {
  457.     register struct nspcb *nsp;
  458.     register struct ifaddr *ifa;
  459.     /*
  460.      * Give any raw listeners a crack at the packet
  461.      */
  462.     for (nsp = nsrawpcb.nsp_next; nsp != &nsrawpcb; nsp = nsp->nsp_next) {
  463.         struct mbuf *m0 = m_copy(m, 0, (int)M_COPYALL);
  464.         if (m0) {
  465.             register struct idp *idp;
  466.  
  467.             M_PREPEND(m0, sizeof (*idp), M_DONTWAIT);
  468.             if (m0 == NULL)
  469.                 continue;
  470.             idp = mtod(m0, struct idp *);
  471.             idp->idp_sna.x_net = ns_zeronet;
  472.             idp->idp_sna.x_host = ns_thishost;
  473.             if (ifp && (ifp->if_flags & IFF_POINTOPOINT))
  474.                 for(ifa = ifp->if_addrlist; ifa;
  475.                         ifa = ifa->ifa_next) {
  476.                 if (ifa->ifa_addr->sa_family==AF_NS) {
  477.                     idp->idp_sna = IA_SNS(ifa)->sns_addr;
  478.                     break;
  479.                 }
  480.                 }
  481.             idp->idp_len = ntohl(m0->m_pkthdr.len);
  482.             idp_input(m0, nsp);
  483.         }
  484.     }
  485. }
  486.