BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / netiso / clnp_input.c
index c100d58..d7abd5b 100644 (file)
@@ -1,3 +1,38 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)clnp_input.c        7.13 (Berkeley) 5/6/91
+ */
+
 /***********************************************************
                Copyright IBM Corporation 1987
 
 /***********************************************************
                Copyright IBM Corporation 1987
 
@@ -24,35 +59,35 @@ SOFTWARE.
 /*
  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
  */
 /*
  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
  */
-/* $Header: clnp_input.c,v 4.4 88/09/08 08:38:15 hagens Exp $ */
-/* $Source: /usr/argo/sys/netiso/RCS/clnp_input.c,v $ */
-/*     @(#)clnp_input.c        7.2 (Berkeley) %G% */
-
-#ifndef lint
-static char *rcsid = "$Header: clnp_input.c,v 4.4 88/09/08 08:38:15 hagens Exp $";
-#endif lint
-
-#include "../h/types.h"
-#include "../h/param.h"
-#include "../h/mbuf.h"
-#include "../h/domain.h"
-#include "../h/protosw.h"
-#include "../h/socket.h"
-#include "../h/socketvar.h"
-#include "../h/errno.h"
-#include "../h/time.h"
+/* $Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $ */
+/* $Source: /var/src/sys/netiso/RCS/clnp_input.c,v $ */
+
+#include "types.h"
+#include "param.h"
+#include "mbuf.h"
+#include "domain.h"
+#include "protosw.h"
+#include "socket.h"
+#include "socketvar.h"
+#include "errno.h"
+#include "time.h"
 
 #include "../net/if.h"
 
 #include "../net/if.h"
+#include "../net/if_types.h"
 #include "../net/route.h"
 
 #include "../net/route.h"
 
-#include "../netiso/iso.h"
-#include "../netiso/iso_var.h"
-#include "../netiso/iso_snpac.h"
-#include "../netiso/clnp.h"
-#include "../netiso/clnl.h"
-#include "../netiso/esis.h"
-#include "../netiso/clnp_stat.h"
-#include "../netiso/argo_debug.h"
+#include "iso.h"
+#include "iso_var.h"
+#include "iso_snpac.h"
+#include "clnp.h"
+#include "clnl.h"
+#include "esis.h"
+#include "../netinet/in_systm.h"
+#include "../netinet/ip.h"
+#include "../netinet/if_ether.h"
+#include "eonvar.h"
+#include "clnp_stat.h"
+#include "argo_debug.h"
 
 #ifdef ISO
 u_char         clnp_protox[ISOPROTO_MAX];
 
 #ifdef ISO
 u_char         clnp_protox[ISOPROTO_MAX];
@@ -120,7 +155,6 @@ clnlintr()
 {
        register struct mbuf            *m;             /* ptr to first mbuf of pkt */
        register struct clnl_fixed      *clnl;  /* ptr to fixed part of clnl hdr */
 {
        register struct mbuf            *m;             /* ptr to first mbuf of pkt */
        register struct clnl_fixed      *clnl;  /* ptr to fixed part of clnl hdr */
-       struct ifnet                            *ifp;   /* ptr to interface pkt arrived on */
        int                                                     s;              /* save and restore priority */
        struct clnl_protosw                     *clnlsw;/* ptr to protocol switch */
        struct snpa_hdr                         sh;             /* subnetwork hdr */
        int                                                     s;              /* save and restore priority */
        struct clnl_protosw                     *clnlsw;/* ptr to protocol switch */
        struct snpa_hdr                         sh;             /* subnetwork hdr */
@@ -130,24 +164,50 @@ clnlintr()
         */
 next:
        s = splimp();
         */
 next:
        s = splimp();
-
        /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
        IF_DEQUEUE(&clnlintrq, m);
        /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
        IF_DEQUEUE(&clnlintrq, m);
+       splx(s);
 
 
 
 
-       splx(s);
        if (m == 0)             /* nothing to do */
                return;
        if (m == 0)             /* nothing to do */
                return;
-       if (m->m_flags & M_PKTHDR == 0) {
+       if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) {
                m_freem(m);
                goto next;
                m_freem(m);
                goto next;
+       } else {
+               register struct ifaddr *ifa;
+               for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next)
+                       if (ifa->ifa_addr->sa_family == AF_ISO)
+                               break;
+               if (ifa == 0) {
+                       m_freem(m);
+                       goto next;
+               }
+       }
+       bzero((caddr_t)&sh, sizeof(sh));
+       sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST);
+       switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) {
+               extern int ether_output();
+       case IFT_EON:
+               bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long));
+               bcopy(sizeof(u_long) + mtod(m, caddr_t),
+                                       (caddr_t)sh.snh_shost, sizeof(u_long));
+               sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) +
+                                                               _offsetof(struct eon_hdr, eonh_class)];
+               m->m_data += EONIPLEN;
+               m->m_len -= EONIPLEN;
+               m->m_pkthdr.len -= EONIPLEN;
+               break;
+
+       default:
+               if (sh.snh_ifp->if_output == ether_output) {
+                       bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost),
+                               (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost));
+                       m->m_data += sizeof (struct ether_header);
+                       m->m_len -= sizeof (struct ether_header);
+                       m->m_pkthdr.len -= sizeof (struct ether_header);
+               }
        }
        }
-       bcopy((caddr_t)(mtod(m, struct llc_etherhdr *)->dst),
-               (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost));
-       m->m_data += sizeof (struct llc_etherhdr);
-       m->m_len -= sizeof (struct llc_etherhdr);
-       m->m_pkthdr.len -= sizeof (struct llc_etherhdr);
-       sh.snh_ifp = m->m_pkthdr.rcvif;
        IFDEBUG(D_INPUT)
                int i;
                printf("clnlintr: src:");
        IFDEBUG(D_INPUT)
                int i;
                printf("clnlintr: src:");
@@ -189,7 +249,7 @@ next:
         *      Note: m_pullup will allocate a cluster mbuf if necessary
         */
        if (clnl->cnf_hdr_len > m->m_len) {
         *      Note: m_pullup will allocate a cluster mbuf if necessary
         */
        if (clnl->cnf_hdr_len > m->m_len) {
-               if ((m = m_pullup(m, clnl->cnf_hdr_len)) == 0) {
+               if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) {
                        INCSTAT(cns_badhlen);   /* TODO: use clnl stats */
                        goto next;      /* m_pullup discards mbuf */
                }
                        INCSTAT(cns_badhlen);   /* TODO: use clnl stats */
                        goto next;      /* m_pullup discards mbuf */
                }
@@ -220,13 +280,15 @@ next:
  *     TODO: I would like to make seg_part a pointer into the mbuf, but 
  *     will it be correctly aligned?
  */
  *     TODO: I would like to make seg_part a pointer into the mbuf, but 
  *     will it be correctly aligned?
  */
-int clnp_input(m, shp)
+clnp_input(m, shp)
 struct mbuf            *m;             /* ptr to first mbuf of pkt */
 struct snpa_hdr        *shp;   /* subnetwork header */
 {
        register struct clnp_fixed      *clnp;  /* ptr to fixed part of header */
 struct mbuf            *m;             /* ptr to first mbuf of pkt */
 struct snpa_hdr        *shp;   /* subnetwork header */
 {
        register struct clnp_fixed      *clnp;  /* ptr to fixed part of header */
-       struct iso_addr                         src;    /* source address of pkt */
-       struct iso_addr                         dst;    /* destination address of pkt */
+       struct sockaddr_iso                     source; /* source address of pkt */
+       struct sockaddr_iso                     target; /* destination address of pkt */
+#define src    source.siso_addr
+#define dst    target.siso_addr
        caddr_t                                         hoff;   /* current offset in packet */
        caddr_t                                         hend;   /* address of end of header info */
        struct clnp_segment                     seg_part; /* segment part of hdr */
        caddr_t                                         hoff;   /* current offset in packet */
        caddr_t                                         hend;   /* address of end of header info */
        struct clnp_segment                     seg_part; /* segment part of hdr */
@@ -234,16 +296,18 @@ struct snpa_hdr   *shp;   /* subnetwork header */
        int                                                     seg_len;/* length of packet data&hdr in bytes */
        struct clnp_optidx                      oidx, *oidxp = NULL;    /* option index */
        extern int                                      iso_systype;    /* used by ESIS config resp */
        int                                                     seg_len;/* length of packet data&hdr in bytes */
        struct clnp_optidx                      oidx, *oidxp = NULL;    /* option index */
        extern int                                      iso_systype;    /* used by ESIS config resp */
+       extern struct sockaddr_iso      blank_siso;             /* used for initializing */
+       int                                                     need_afrin = 0; 
+                                                                               /* true if congestion experienced */
+                                                                               /* which means you need afrin nose */
+                                                                               /* spray. How clever! */
 
        IFDEBUG(D_INPUT)
                printf(
 
        IFDEBUG(D_INPUT)
                printf(
-               "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, data:\n", 
-                       m->m_len, m->m_type);
-       ENDDEBUG
-       IFDEBUG(D_DUMPIN)
-               printf("clnp_input: first mbuf:\n");
-               dump_buf(mtod(m, caddr_t), m->m_len);
+                  "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n", 
+                       m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal");
        ENDDEBUG
        ENDDEBUG
+       need_afrin = 0;
 
        /*
         *      If no iso addresses have been set, there is nothing
 
        /*
         *      If no iso addresses have been set, there is nothing
@@ -257,11 +321,24 @@ struct snpa_hdr   *shp;   /* subnetwork header */
        INCSTAT(cns_total);
        clnp = mtod(m, struct clnp_fixed *);
 
        INCSTAT(cns_total);
        clnp = mtod(m, struct clnp_fixed *);
 
+       IFDEBUG(D_DUMPIN)
+               struct mbuf *mhead;
+               int                     total_len = 0;
+               printf("clnp_input: clnp header:\n");
+               dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len);
+               printf("clnp_input: mbuf chain:\n");
+               for (mhead = m; mhead != NULL; mhead=mhead->m_next) {
+                       printf("m x%x, len %d\n", mhead, mhead->m_len);
+                       total_len += mhead->m_len;
+               }
+               printf("clnp_input: total length of mbuf chain %d:\n", total_len);
+       ENDDEBUG
+
        /*
         *      Compute checksum (if necessary) and drop packet if
         *      checksum does not match
         */
        /*
         *      Compute checksum (if necessary) and drop packet if
         *      checksum does not match
         */
-       if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, clnp->cnf_hdr_len)) {
+       if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) {
                INCSTAT(cns_badcsum);
                clnp_discard(m, GEN_BADCSUM);
                return;
                INCSTAT(cns_badcsum);
                clnp_discard(m, GEN_BADCSUM);
                return;
@@ -286,8 +363,7 @@ struct snpa_hdr     *shp;   /* subnetwork header */
         *      extract the source and destination address
         *      drop packet on failure
         */
         *      extract the source and destination address
         *      drop packet on failure
         */
-       bzero((caddr_t)&src, sizeof(src));
-       bzero((caddr_t)&dst, sizeof(dst));
+       source = target = blank_siso;
 
        hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
        CLNP_EXTRACT_ADDR(dst, hoff, hend);
 
        hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
        CLNP_EXTRACT_ADDR(dst, hoff, hend);
@@ -312,7 +388,8 @@ struct snpa_hdr     *shp;   /* subnetwork header */
         *      extract the segmentation information, if it is present.
         *      drop packet on failure
         */
         *      extract the segmentation information, if it is present.
         *      drop packet on failure
         */
-       if ((clnp->cnf_type != CLNP_ER) && (clnp->cnf_seg_ok)) {
+       if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
+               (clnp->cnf_type & CNF_SEG_OK)) {
                if (hoff + sizeof(struct clnp_segment) > hend) {
                        INCSTAT(cns_noseg);
                        clnp_discard(m, GEN_INCOMPLETE);
                if (hoff + sizeof(struct clnp_segment) > hend) {
                        INCSTAT(cns_noseg);
                        clnp_discard(m, GEN_INCOMPLETE);
@@ -346,9 +423,22 @@ struct snpa_hdr    *shp;   /* subnetwork header */
 
                /* the er option is valid with ER pdus only */
                if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && 
 
                /* the er option is valid with ER pdus only */
                if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && 
-                       (clnp->cnf_type != CLNP_ER))
+                       ((clnp->cnf_type & CNF_TYPE) != CLNP_ER))
                        errcode = DISC_UNSUPPOPT;
 
                        errcode = DISC_UNSUPPOPT;
 
+#ifdef DECBIT
+               /* check if the congestion experienced bit is set */
+               if (oidxp->cni_qos_formatp) {
+                       caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp);
+                       u_char  qos = *qosp;
+
+                       need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) ==
+                               (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED));
+                       if (need_afrin)
+                               INCSTAT(cns_congest_rcvd);
+               }
+#endif DECBIT
+
                if (errcode != 0) {
                        clnp_discard(m, (char)errcode);
                        IFDEBUG(D_INPUT)
                if (errcode != 0) {
                        clnp_discard(m, (char)errcode);
                        IFDEBUG(D_INPUT)
@@ -376,11 +466,11 @@ struct snpa_hdr   *shp;   /* subnetwork header */
         *      If the packet received was sent to the multicast address
         *      all end systems, then send an esh to the source
         */
         *      If the packet received was sent to the multicast address
         *      all end systems, then send an esh to the source
         */
-       if ((IS_MULTICAST(shp->snh_dhost)) && (iso_systype == SNPA_ES)) {
+       if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) {
                extern short esis_holding_time;
 
                esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
                extern short esis_holding_time;
 
                esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
-                       shp->snh_shost, 6);
+                       shp->snh_shost, 6, &dst);
        }
 
        /*
        }
 
        /*
@@ -390,13 +480,15 @@ struct snpa_hdr   *shp;   /* subnetwork header */
         *      by the reassembly code (either stored or deleted). In either case
         *      we should have nothing more to do with it.
         */
         *      by the reassembly code (either stored or deleted). In either case
         *      we should have nothing more to do with it.
         */
-       if ((clnp->cnf_type != CLNP_ER) && (clnp->cnf_seg_ok) &&
+       if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
+               (clnp->cnf_type & CNF_SEG_OK) &&
                (seg_len != seg_part.cng_tot_len)) {
                struct mbuf     *m0;
 
                if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
                        m = m0;
                        clnp = mtod(m, struct clnp_fixed *);
                (seg_len != seg_part.cng_tot_len)) {
                struct mbuf     *m0;
 
                if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
                        m = m0;
                        clnp = mtod(m, struct clnp_fixed *);
+                       INCSTAT(cns_reassembled);
                } else {
                        return;
                }
                } else {
                        return;
                }
@@ -404,14 +496,14 @@ struct snpa_hdr   *shp;   /* subnetwork header */
        
        /*
         *      give the packet to the higher layer
        
        /*
         *      give the packet to the higher layer
-        *      TODO: how do we tell TP that congestion bit is on in QOS option?
         *
         *      Note: the total length of packet
         *      is the total length field of the segmentation part,
         *      or, if absent, the segment length field of the
         *      header.
         */
         *
         *      Note: the total length of packet
         *      is the total length field of the segmentation part,
         *      or, if absent, the segment length field of the
         *      header.
         */
-       switch (clnp->cnf_type) {
+       INCSTAT(cns_delivered);
+       switch (clnp->cnf_type & CNF_TYPE) {
        case CLNP_ER:
                /*
                 *      This ER must have the er option.
        case CLNP_ER:
                /*
                 *      This ER must have the er option.
@@ -425,17 +517,17 @@ struct snpa_hdr   *shp;   /* subnetwork header */
                break;
 
        case CLNP_DT:
                break;
 
        case CLNP_DT:
-               (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &src, &dst,
-                       clnp->cnf_hdr_len);
+               (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target,
+                       clnp->cnf_hdr_len, need_afrin);
                break;
 
        case CLNP_RAW:
        case CLNP_ECR:
                IFDEBUG(D_INPUT)
                        printf("clnp_input: raw input of %d bytes\n",
                break;
 
        case CLNP_RAW:
        case CLNP_ECR:
                IFDEBUG(D_INPUT)
                        printf("clnp_input: raw input of %d bytes\n",
-                               clnp->cnf_seg_ok ? seg_part.cng_tot_len : seg_len);
+                               clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len);
                ENDDEBUG
                ENDDEBUG
-               (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &src, &dst,
+               (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target,
                                        clnp->cnf_hdr_len);
                break;
 
                                        clnp->cnf_hdr_len);
                break;
 
@@ -447,26 +539,26 @@ struct snpa_hdr   *shp;   /* subnetwork header */
                 *      Switch the source and destination address,
                 */
                hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
                 *      Switch the source and destination address,
                 */
                hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
-               CLNP_INSERT_ADDR(hoff, &src);
-               CLNP_INSERT_ADDR(hoff, &dst);
-               clnp->cnf_type = CLNP_ECR;
+               CLNP_INSERT_ADDR(hoff, src);
+               CLNP_INSERT_ADDR(hoff, dst);
+               clnp->cnf_type &= ~CNF_TYPE;
+               clnp->cnf_type |= CLNP_ECR;
 
                /*
                 *      Forward back to sender
                 */
 
                /*
                 *      Forward back to sender
                 */
-               clnp_forward(m, clnp->cnf_seg_ok ? seg_part.cng_tot_len : seg_len,
-                       &src, oidxp, seg_off, shp);
+               clnp_forward(m, (int)
+                       (clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len),
+                       &src, oidxp, seg_off, 0);
                break;
 
        default:
                break;
 
        default:
-               printf("clnp_input: unknown clnp pkt type %d\n", clnp->cnf_type);
+               printf("clnp_input: unknown clnp pkt type %d\n",
+                       clnp->cnf_type & CNF_TYPE);
+               clnp_stat.cns_delivered--;
+               clnp_stat.cns_noproto++;
                clnp_discard(m, GEN_HDRSYNTAX);
                break;
        }
 }
                clnp_discard(m, GEN_HDRSYNTAX);
                break;
        }
 }
-
-int clnp_ctlinput()
-{
-}
-
 #endif ISO
 #endif ISO