[BACK]Return to ip_input.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / netinet

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/netinet/ip_input.c between version 1.30 and 1.62

version 1.30, 1996/03/16 23:53:58 version 1.62, 1998/04/29 20:45:30
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
   
   /*-
    * Copyright (c) 1998 The NetBSD Foundation, Inc.
    * All rights reserved.
    *
    * This code is derived from software contributed to The NetBSD Foundation
    * by Public Access Networks Corporation ("Panix").  It was developed under
    * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon.
    *
    * 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 NetBSD
    *      Foundation, Inc. and its contributors.
    * 4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
    */
   
 /*  /*
  * Copyright (c) 1982, 1986, 1988, 1993   * Copyright (c) 1982, 1986, 1988, 1993
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
Line 35 
Line 72 
  *      @(#)ip_input.c  8.2 (Berkeley) 1/4/94   *      @(#)ip_input.c  8.2 (Berkeley) 1/4/94
  */   */
   
   #include "opt_gateway.h"
   #include "opt_mrouting.h"
   
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
Line 42 
Line 82 
 #include <sys/domain.h>  #include <sys/domain.h>
 #include <sys/protosw.h>  #include <sys/protosw.h>
 #include <sys/socket.h>  #include <sys/socket.h>
   #include <sys/socketvar.h>
 #include <sys/errno.h>  #include <sys/errno.h>
 #include <sys/time.h>  #include <sys/time.h>
 #include <sys/kernel.h>  #include <sys/kernel.h>
Line 51 
Line 92 
 #include <sys/sysctl.h>  #include <sys/sysctl.h>
   
 #include <net/if.h>  #include <net/if.h>
   #include <net/if_dl.h>
 #include <net/route.h>  #include <net/route.h>
   #include <net/pfil.h>
   
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netinet/in_systm.h>  #include <netinet/in_systm.h>
Line 72 
Line 115 
 #define IPSENDREDIRECTS 1  #define IPSENDREDIRECTS 1
 #endif  #endif
 #ifndef IPFORWSRCRT  #ifndef IPFORWSRCRT
 #define IPFORWSRCRT     1       /* allow source-routed packets */  #define IPFORWSRCRT     1       /* forward source-routed packets */
   #endif
   #ifndef IPALLOWSRCRT
   #define IPALLOWSRCRT    1       /* allow source-routed packets */
   #endif
   #ifndef IPMTUDISC
   #define IPMTUDISC       0
   #endif
   #ifndef IPMTUDISCTIMEOUT
   #define IPMTUDISCTIMEOUT (10 * 60)      /* as per RFC 1191 */
 #endif  #endif
   
 /*  /*
  * Note: DIRECTED_BROADCAST is handled this way so that previous   * Note: DIRECTED_BROADCAST is handled this way so that previous
  * configuration using this option will Just Work.   * configuration using this option will Just Work.
Line 90  int ipsendredirects = IPSENDREDIRECTS;
Line 143  int ipsendredirects = IPSENDREDIRECTS;
 int     ip_defttl = IPDEFTTL;  int     ip_defttl = IPDEFTTL;
 int     ip_forwsrcrt = IPFORWSRCRT;  int     ip_forwsrcrt = IPFORWSRCRT;
 int     ip_directedbcast = IPDIRECTEDBCAST;  int     ip_directedbcast = IPDIRECTEDBCAST;
   int     ip_allowsrcrt = IPALLOWSRCRT;
   int     ip_mtudisc = IPMTUDISC;
   u_int   ip_mtudisc_timeout = IPMTUDISCTIMEOUT;
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
 int     ipprintfs = 0;  int     ipprintfs = 0;
 #endif  #endif
   
   struct rttimer_queue *ip_mtudisc_timeout_q = NULL;
   
 extern  struct domain inetdomain;  extern  struct domain inetdomain;
 extern  struct protosw inetsw[];  extern  struct protosw inetsw[];
 u_char  ip_protox[IPPROTO_MAX];  u_char  ip_protox[IPPROTO_MAX];
 int     ipqmaxlen = IFQ_MAXLEN;  int     ipqmaxlen = IFQ_MAXLEN;
 struct  in_ifaddrhead in_ifaddr;  struct  in_ifaddrhead in_ifaddr;
   struct  in_ifaddrhashhead *in_ifaddrhashtbl;
 struct  ifqueue ipintrq;  struct  ifqueue ipintrq;
   
 /*  /*
Line 117  static struct ip_srcrt {
Line 176  static struct ip_srcrt {
 } ip_srcrt;  } ip_srcrt;
   
 static void save_rte __P((u_char *, struct in_addr));  static void save_rte __P((u_char *, struct in_addr));
   
 /*  /*
  * IP initialization: fill in IP protocol switch table.   * IP initialization: fill in IP protocol switch table.
  * All protocols not implemented in kernel go to raw IP protocol handler.   * All protocols not implemented in kernel go to raw IP protocol handler.
Line 141  ip_init()
Line 201  ip_init()
         ip_id = time.tv_sec & 0xffff;          ip_id = time.tv_sec & 0xffff;
         ipintrq.ifq_maxlen = ipqmaxlen;          ipintrq.ifq_maxlen = ipqmaxlen;
         TAILQ_INIT(&in_ifaddr);          TAILQ_INIT(&in_ifaddr);
           in_ifaddrhashtbl =
               hashinit(IN_IFADDR_HASH_SIZE, M_IFADDR, M_WAITOK, &in_ifaddrhash);
           if (ip_mtudisc != 0)
                   ip_mtudisc_timeout_q =
                       rt_timer_queue_create(ip_mtudisc_timeout);
 }  }
   
 struct  sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };  struct  sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET };
Line 153  struct route ipforward_rt;
Line 218  struct route ipforward_rt;
 void  void
 ipintr()  ipintr()
 {  {
         register struct ip *ip;          register struct ip *ip = NULL;
         register struct mbuf *m;          register struct mbuf *m;
         register struct ipq *fp;          register struct ipq *fp;
         register struct in_ifaddr *ia;          register struct in_ifaddr *ia;
           register struct ifaddr *ifa;
         struct ipqent *ipqe;          struct ipqent *ipqe;
         int hlen, mff, s;          int hlen = 0, mff, len, s;
   #ifdef PFIL_HOOKS
           struct packet_filter_hook *pfh;
           struct mbuf *m0;
           int rv;
   #endif /* PFIL_HOOKS */
   
 next:  next:
         /*          /*
Line 212  next:
Line 283  next:
          * Convert fields to host representation.           * Convert fields to host representation.
          */           */
         NTOHS(ip->ip_len);          NTOHS(ip->ip_len);
         if (ip->ip_len < hlen) {  
                 ipstat.ips_badlen++;  
                 goto bad;  
         }  
         NTOHS(ip->ip_id);          NTOHS(ip->ip_id);
         NTOHS(ip->ip_off);          NTOHS(ip->ip_off);
           len = ip->ip_len;
   
         /*          /*
          * Check that the amount of data in the buffers           * Check that the amount of data in the buffers
Line 225  next:
Line 293  next:
          * Trim mbufs if longer than we expect.           * Trim mbufs if longer than we expect.
          * Drop packet if shorter than we expect.           * Drop packet if shorter than we expect.
          */           */
         if (m->m_pkthdr.len < ip->ip_len) {          if (m->m_pkthdr.len < len) {
                 ipstat.ips_tooshort++;                  ipstat.ips_tooshort++;
                 goto bad;                  goto bad;
         }          }
         if (m->m_pkthdr.len > ip->ip_len) {          if (m->m_pkthdr.len > len) {
                 if (m->m_len == m->m_pkthdr.len) {                  if (m->m_len == m->m_pkthdr.len) {
                         m->m_len = ip->ip_len;                          m->m_len = len;
                         m->m_pkthdr.len = ip->ip_len;                          m->m_pkthdr.len = len;
                 } else                  } else
                         m_adj(m, ip->ip_len - m->m_pkthdr.len);                          m_adj(m, len - m->m_pkthdr.len);
         }          }
   
   #ifdef PFIL_HOOKS
           /*
            * Run through list of hooks for input packets.
            */
           m0 = m;
           for (pfh = pfil_hook_get(PFIL_IN); pfh; pfh = pfh->pfil_link.tqe_next)
                   if (pfh->pfil_func) {
                           rv = pfh->pfil_func(ip, hlen, m->m_pkthdr.rcvif, 0, &m0);
                           if (rv)
                                   goto next;
                           ip = mtod(m = m0, struct ip *);
                   }
   #endif /* PFIL_HOOKS */
   
         /*          /*
          * Process options and, if not destined for us,           * Process options and, if not destined for us,
          * ship it on.  ip_dooptions returns 1 when an           * ship it on.  ip_dooptions returns 1 when an
Line 250  next:
Line 332  next:
         /*          /*
          * Check our list of addresses, to see if the packet is for us.           * Check our list of addresses, to see if the packet is for us.
          */           */
         for (ia = in_ifaddr.tqh_first; ia; ia = ia->ia_list.tqe_next) {          INADDR_TO_IA(ip->ip_dst, ia);
                 if (ip->ip_dst.s_addr == ia->ia_addr.sin_addr.s_addr)          if (ia != NULL) goto ours;
                         goto ours;          if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) {
                 if (((ip_directedbcast == 0) || (ip_directedbcast &&                  for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first;
                     ia->ia_ifp == m->m_pkthdr.rcvif)) &&                      ifa != NULL; ifa = ifa->ifa_list.tqe_next) {
                     (ia->ia_ifp->if_flags & IFF_BROADCAST)) {                          if (ifa->ifa_addr->sa_family != AF_INET) continue;
                         if (ip->ip_dst.s_addr == ia->ia_broadaddr.sin_addr.s_addr ||                          ia = ifatoia(ifa);
                             ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr ||                          if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) ||
                               in_hosteq(ip->ip_dst, ia->ia_netbroadcast) ||
                             /*                              /*
                              * Look for all-0's host part (old broadcast addr),                               * Look for all-0's host part (old broadcast addr),
                              * either for subnet or net.                               * either for subnet or net.
Line 265  next:
Line 348  next:
                             ip->ip_dst.s_addr == ia->ia_subnet ||                              ip->ip_dst.s_addr == ia->ia_subnet ||
                             ip->ip_dst.s_addr == ia->ia_net)                              ip->ip_dst.s_addr == ia->ia_net)
                                 goto ours;                                  goto ours;
                           /*
                            * An interface with IP address zero accepts
                            * all packets that arrive on that interface.
                            */
                           if (in_nullhost(ia->ia_addr.sin_addr))
                                   goto ours;
                 }                  }
         }          }
         if (IN_MULTICAST(ip->ip_dst.s_addr)) {          if (IN_MULTICAST(ip->ip_dst.s_addr)) {
Line 324  next:
Line 413  next:
                 goto ours;                  goto ours;
         }          }
         if (ip->ip_dst.s_addr == INADDR_BROADCAST ||          if (ip->ip_dst.s_addr == INADDR_BROADCAST ||
             ip->ip_dst.s_addr == INADDR_ANY)              in_nullhost(ip->ip_dst))
                 goto ours;                  goto ours;
   
         /*          /*
Line 345  ours:
Line 434  ours:
          * if the packet was previously fragmented,           * if the packet was previously fragmented,
          * but it's not worth the time; just let them time out.)           * but it's not worth the time; just let them time out.)
          */           */
         if (ip->ip_off &~ IP_DF) {          if (ip->ip_off & ~(IP_DF|IP_RF)) {
                 if (m->m_flags & M_EXT) {               /* XXX */  
                         if ((m = m_pullup(m, sizeof (struct ip))) == 0) {  
                                 ipstat.ips_toosmall++;  
                                 goto next;  
                         }  
                         ip = mtod(m, struct ip *);  
                 }  
                 /*                  /*
                  * Look for queue of fragments                   * Look for queue of fragments
                  * of this datagram.                   * of this datagram.
                  */                   */
                 for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next)                  for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next)
                         if (ip->ip_id == fp->ipq_id &&                          if (ip->ip_id == fp->ipq_id &&
                             ip->ip_src.s_addr == fp->ipq_src.s_addr &&                              in_hosteq(ip->ip_src, fp->ipq_src) &&
                             ip->ip_dst.s_addr == fp->ipq_dst.s_addr &&                              in_hosteq(ip->ip_dst, fp->ipq_dst) &&
                             ip->ip_p == fp->ipq_p)                              ip->ip_p == fp->ipq_p)
                                 goto found;                                  goto found;
                 fp = 0;                  fp = 0;
Line 399  found:
Line 481  found:
                                 goto bad;                                  goto bad;
                         }                          }
                         ipqe->ipqe_mff = mff;                          ipqe->ipqe_mff = mff;
                           ipqe->ipqe_m = m;
                         ipqe->ipqe_ip = ip;                          ipqe->ipqe_ip = ip;
                         ip = ip_reass(ipqe, fp);                          m = ip_reass(ipqe, fp);
                         if (ip == 0)                          if (m == 0)
                                 goto next;                                  goto next;
                         ipstat.ips_reassembled++;                          ipstat.ips_reassembled++;
                         m = dtom(ip);                          ip = mtod(m, struct ip *);
                 } else                  } else
                         if (fp)                          if (fp)
                                 ip_freef(fp);                                  ip_freef(fp);
Line 428  bad:
Line 511  bad:
  * reassembly of this datagram already exists, then it   * reassembly of this datagram already exists, then it
  * is given as fp; otherwise have to make a chain.   * is given as fp; otherwise have to make a chain.
  */   */
 struct ip *  struct mbuf *
 ip_reass(ipqe, fp)  ip_reass(ipqe, fp)
         register struct ipqent *ipqe;          register struct ipqent *ipqe;
         register struct ipq *fp;          register struct ipq *fp;
 {  {
         register struct mbuf *m = dtom(ipqe->ipqe_ip);          register struct mbuf *m = ipqe->ipqe_m;
         register struct ipqent *nq, *p, *q;          register struct ipqent *nq, *p, *q;
         struct ip *ip;          struct ip *ip;
         struct mbuf *t;          struct mbuf *t;
Line 451  ip_reass(ipqe, fp)
Line 534  ip_reass(ipqe, fp)
          * If first fragment to arrive, create a reassembly queue.           * If first fragment to arrive, create a reassembly queue.
          */           */
         if (fp == 0) {          if (fp == 0) {
                 if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)                  MALLOC(fp, struct ipq *, sizeof (struct ipq),
                       M_FTABLE, M_NOWAIT);
                   if (fp == NULL)
                         goto dropfrag;                          goto dropfrag;
                 fp = mtod(t, struct ipq *);  
                 LIST_INSERT_HEAD(&ipq, fp, ipq_q);                  LIST_INSERT_HEAD(&ipq, fp, ipq_q);
                 fp->ipq_ttl = IPFRAGTTL;                  fp->ipq_ttl = IPFRAGTTL;
                 fp->ipq_p = ipqe->ipqe_ip->ip_p;                  fp->ipq_p = ipqe->ipqe_ip->ip_p;
Line 484  ip_reass(ipqe, fp)
Line 568  ip_reass(ipqe, fp)
                 if (i > 0) {                  if (i > 0) {
                         if (i >= ipqe->ipqe_ip->ip_len)                          if (i >= ipqe->ipqe_ip->ip_len)
                                 goto dropfrag;                                  goto dropfrag;
                         m_adj(dtom(ipqe->ipqe_ip), i);                          m_adj(ipqe->ipqe_m, i);
                         ipqe->ipqe_ip->ip_off += i;                          ipqe->ipqe_ip->ip_off += i;
                         ipqe->ipqe_ip->ip_len -= i;                          ipqe->ipqe_ip->ip_len -= i;
                 }                  }
Line 501  ip_reass(ipqe, fp)
Line 585  ip_reass(ipqe, fp)
                 if (i < q->ipqe_ip->ip_len) {                  if (i < q->ipqe_ip->ip_len) {
                         q->ipqe_ip->ip_len -= i;                          q->ipqe_ip->ip_len -= i;
                         q->ipqe_ip->ip_off += i;                          q->ipqe_ip->ip_off += i;
                         m_adj(dtom(q->ipqe_ip), i);                          m_adj(q->ipqe_m, i);
                         break;                          break;
                 }                  }
                 nq = q->ipqe_q.le_next;                  nq = q->ipqe_q.le_next;
                 m_freem(dtom(q->ipqe_ip));                  m_freem(q->ipqe_m);
                 LIST_REMOVE(q, ipqe_q);                  LIST_REMOVE(q, ipqe_q);
                 FREE(q, M_IPQ);                  FREE(q, M_IPQ);
         }          }
Line 531  insert:
Line 615  insert:
                 return (0);                  return (0);
   
         /*          /*
          * Reassembly is complete; concatenate fragments.           * Reassembly is complete.  Check for a bogus message size and
            * concatenate fragments.
          */           */
         q = fp->ipq_fragq.lh_first;          q = fp->ipq_fragq.lh_first;
         ip = q->ipqe_ip;          ip = q->ipqe_ip;
         m = dtom(q->ipqe_ip);          if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
                   ipstat.ips_toolong++;
                   ip_freef(fp);
                   return (0);
           }
           m = q->ipqe_m;
         t = m->m_next;          t = m->m_next;
         m->m_next = 0;          m->m_next = 0;
         m_cat(m, t);          m_cat(m, t);
         nq = q->ipqe_q.le_next;          nq = q->ipqe_q.le_next;
         FREE(q, M_IPQ);          FREE(q, M_IPQ);
         for (q = nq; q != NULL; q = nq) {          for (q = nq; q != NULL; q = nq) {
                 t = dtom(q->ipqe_ip);                  t = q->ipqe_m;
                 nq = q->ipqe_q.le_next;                  nq = q->ipqe_q.le_next;
                 FREE(q, M_IPQ);                  FREE(q, M_IPQ);
                 m_cat(m, t);                  m_cat(m, t);
Line 558  insert:
Line 648  insert:
         ip->ip_src = fp->ipq_src;          ip->ip_src = fp->ipq_src;
         ip->ip_dst = fp->ipq_dst;          ip->ip_dst = fp->ipq_dst;
         LIST_REMOVE(fp, ipq_q);          LIST_REMOVE(fp, ipq_q);
         (void) m_free(dtom(fp));          FREE(fp, M_FTABLE);
         m->m_len += (ip->ip_hl << 2);          m->m_len += (ip->ip_hl << 2);
         m->m_data -= (ip->ip_hl << 2);          m->m_data -= (ip->ip_hl << 2);
         /* some debugging cruft by sklower, below, will go away soon */          /* some debugging cruft by sklower, below, will go away soon */
         if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */          if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
                 register int plen = 0;                  register int plen = 0;
                 for (t = m; m; m = m->m_next)                  for (t = m; t; t = t->m_next)
                         plen += m->m_len;                          plen += t->m_len;
                 t->m_pkthdr.len = plen;                  m->m_pkthdr.len = plen;
         }          }
         return (ip);          return (m);
   
 dropfrag:  dropfrag:
         ipstat.ips_fragdropped++;          ipstat.ips_fragdropped++;
Line 589  ip_freef(fp)
Line 679  ip_freef(fp)
   
         for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) {          for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) {
                 p = q->ipqe_q.le_next;                  p = q->ipqe_q.le_next;
                 m_freem(dtom(q->ipqe_ip));                  m_freem(q->ipqe_m);
                 LIST_REMOVE(q, ipqe_q);                  LIST_REMOVE(q, ipqe_q);
                 FREE(q, M_IPQ);                  FREE(q, M_IPQ);
         }          }
         LIST_REMOVE(fp, ipq_q);          LIST_REMOVE(fp, ipq_q);
         (void) m_free(dtom(fp));          FREE(fp, M_FTABLE);
 }  }
   
 /*  /*
Line 682  ip_dooptions(m)
Line 772  ip_dooptions(m)
                  */                   */
                 case IPOPT_LSRR:                  case IPOPT_LSRR:
                 case IPOPT_SSRR:                  case IPOPT_SSRR:
                           if (ip_allowsrcrt == 0) {
                                   type = ICMP_UNREACH;
                                   code = ICMP_UNREACH_NET_PROHIB;
                                   goto bad;
                           }
                         if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {                          if ((off = cp[IPOPT_OFFSET]) < IPOPT_MINOFF) {
                                 code = &cp[IPOPT_OFFSET] - (u_char *)ip;                                  code = &cp[IPOPT_OFFSET] - (u_char *)ip;
                                 goto bad;                                  goto bad;
Line 841  ip_rtaddr(dst)
Line 936  ip_rtaddr(dst)
   
         sin = satosin(&ipforward_rt.ro_dst);          sin = satosin(&ipforward_rt.ro_dst);
   
         if (ipforward_rt.ro_rt == 0 || dst.s_addr != sin->sin_addr.s_addr) {          if (ipforward_rt.ro_rt == 0 || !in_hosteq(dst, sin->sin_addr)) {
                 if (ipforward_rt.ro_rt) {                  if (ipforward_rt.ro_rt) {
                         RTFREE(ipforward_rt.ro_rt);                          RTFREE(ipforward_rt.ro_rt);
                         ipforward_rt.ro_rt = 0;                          ipforward_rt.ro_rt = 0;
Line 1016  ip_forward(m, srcrt)
Line 1111  ip_forward(m, srcrt)
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
         if (ipprintfs)          if (ipprintfs)
                 printf("forward: src %x dst %x ttl %x\n",                  printf("forward: src %x dst %x ttl %x\n",
                        ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl);                      ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl);
 #endif  #endif
         if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {          if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) {
                 ipstat.ips_cantforward++;                  ipstat.ips_cantforward++;
Line 1032  ip_forward(m, srcrt)
Line 1127  ip_forward(m, srcrt)
   
         sin = satosin(&ipforward_rt.ro_dst);          sin = satosin(&ipforward_rt.ro_dst);
         if ((rt = ipforward_rt.ro_rt) == 0 ||          if ((rt = ipforward_rt.ro_rt) == 0 ||
             ip->ip_dst.s_addr != sin->sin_addr.s_addr) {              !in_hosteq(ip->ip_dst, sin->sin_addr)) {
                 if (ipforward_rt.ro_rt) {                  if (ipforward_rt.ro_rt) {
                         RTFREE(ipforward_rt.ro_rt);                          RTFREE(ipforward_rt.ro_rt);
                         ipforward_rt.ro_rt = 0;                          ipforward_rt.ro_rt = 0;
                 }                  }
                 sin->sin_family = AF_INET;                  sin->sin_family = AF_INET;
                 sin->sin_len = sizeof(*sin);                  sin->sin_len = sizeof(struct sockaddr_in);
                 sin->sin_addr = ip->ip_dst;                  sin->sin_addr = ip->ip_dst;
   
                 rtalloc(&ipforward_rt);                  rtalloc(&ipforward_rt);
Line 1050  ip_forward(m, srcrt)
Line 1145  ip_forward(m, srcrt)
         }          }
   
         /*          /*
          * Save at most 64 bytes of the packet in case           * Save at most 68 bytes of the packet in case
          * we need to generate an ICMP message to the src.           * we need to generate an ICMP message to the src.
          */           */
         mcopy = m_copy(m, 0, imin((int)ip->ip_len, 64));          mcopy = m_copy(m, 0, imin((int)ip->ip_len, 68));
   
         /*          /*
          * If forwarding packet using same interface that it came in on,           * If forwarding packet using same interface that it came in on,
Line 1065  ip_forward(m, srcrt)
Line 1160  ip_forward(m, srcrt)
          */           */
         if (rt->rt_ifp == m->m_pkthdr.rcvif &&          if (rt->rt_ifp == m->m_pkthdr.rcvif &&
             (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&              (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 &&
             satosin(rt_key(rt))->sin_addr.s_addr != 0 &&              !in_nullhost(satosin(rt_key(rt))->sin_addr) &&
             ipsendredirects && !srcrt) {              ipsendredirects && !srcrt) {
                 if (rt->rt_ifa &&                  if (rt->rt_ifa &&
                     (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) ==                      (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) ==
Line 1079  ip_forward(m, srcrt)
Line 1174  ip_forward(m, srcrt)
                     code = ICMP_REDIRECT_HOST;                      code = ICMP_REDIRECT_HOST;
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
                     if (ipprintfs)                      if (ipprintfs)
                         printf("redirect (%d) to %x\n", code, (u_int32_t)dest);                          printf("redirect (%d) to %x\n", code, (u_int32_t)dest);
 #endif  #endif
                 }                  }
         }          }
Line 1133  ip_forward(m, srcrt)
Line 1228  ip_forward(m, srcrt)
         icmp_error(mcopy, type, code, dest, destifp);          icmp_error(mcopy, type, code, dest, destifp);
 }  }
   
   void
   ip_savecontrol(inp, mp, ip, m)
           register struct inpcb *inp;
           register struct mbuf **mp;
           register struct ip *ip;
           register struct mbuf *m;
   {
   
           if (inp->inp_socket->so_options & SO_TIMESTAMP) {
                   struct timeval tv;
   
                   microtime(&tv);
                   *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
                       SCM_TIMESTAMP, SOL_SOCKET);
                   if (*mp)
                           mp = &(*mp)->m_next;
           }
           if (inp->inp_flags & INP_RECVDSTADDR) {
                   *mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
                       sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
                   if (*mp)
                           mp = &(*mp)->m_next;
           }
   #ifdef notyet
           /*
            * XXX
            * Moving these out of udp_input() made them even more broken
            * than they already were.
            *      - fenner@parc.xerox.com
            */
           /* options were tossed already */
           if (inp->inp_flags & INP_RECVOPTS) {
                   *mp = sbcreatecontrol((caddr_t) opts_deleted_above,
                       sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP);
                   if (*mp)
                           mp = &(*mp)->m_next;
           }
           /* ip_srcroute doesn't do what we want here, need to fix */
           if (inp->inp_flags & INP_RECVRETOPTS) {
                   *mp = sbcreatecontrol((caddr_t) ip_srcroute(),
                       sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
                   if (*mp)
                           mp = &(*mp)->m_next;
           }
   #endif
           if (inp->inp_flags & INP_RECVIF) {
                   struct sockaddr_dl sdl;
   
                   sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]);
                   sdl.sdl_family = AF_LINK;
                   sdl.sdl_index = m->m_pkthdr.rcvif ?
                       m->m_pkthdr.rcvif->if_index : 0;
                   sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0;
                   *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len,
                       IP_RECVIF, IPPROTO_IP);
                   if (*mp)
                           mp = &(*mp)->m_next;
           }
   }
   
 int  int
 ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)  ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
         int *name;          int *name;
Line 1142  ip_sysctl(name, namelen, oldp, oldlenp, 
Line 1297  ip_sysctl(name, namelen, oldp, oldlenp, 
         void *newp;          void *newp;
         size_t newlen;          size_t newlen;
 {  {
           extern int subnetsarelocal;
   
           int error, old;
   
         /* All sysctl names at this level are terminal. */          /* All sysctl names at this level are terminal. */
         if (namelen != 1)          if (namelen != 1)
                 return (ENOTDIR);                  return (ENOTDIR);
Line 1159  ip_sysctl(name, namelen, oldp, oldlenp, 
Line 1318  ip_sysctl(name, namelen, oldp, oldlenp, 
                 return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));                  return (sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtu));
 #endif  #endif
         case IPCTL_FORWSRCRT:          case IPCTL_FORWSRCRT:
                 /*                  /* Don't allow this to change in a secure environment.  */
                  * Don't allow this to change in a secure environment.  
                  */  
                 if (securelevel > 0)                  if (securelevel > 0)
                         return (EPERM);                          return (sysctl_rdint(oldp, oldlenp, newp,
                 return (sysctl_int(oldp, oldlenp, newp, newlen,                              ip_forwsrcrt));
                     &ip_forwsrcrt));                  else
                           return (sysctl_int(oldp, oldlenp, newp, newlen,
                               &ip_forwsrcrt));
         case IPCTL_DIRECTEDBCAST:          case IPCTL_DIRECTEDBCAST:
                 return (sysctl_int(oldp, oldlenp, newp, newlen,                  return (sysctl_int(oldp, oldlenp, newp, newlen,
                     &ip_directedbcast));                      &ip_directedbcast));
           case IPCTL_ALLOWSRCRT:
                   return (sysctl_int(oldp, oldlenp, newp, newlen,
                       &ip_allowsrcrt));
           case IPCTL_SUBNETSARELOCAL:
                   return (sysctl_int(oldp, oldlenp, newp, newlen,
                       &subnetsarelocal));
           case IPCTL_MTUDISC:
                   error = sysctl_int(oldp, oldlenp, newp, newlen,
                       &ip_mtudisc);
                   if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) {
                           ip_mtudisc_timeout_q =
                               rt_timer_queue_create(ip_mtudisc_timeout);
                   } else if (ip_mtudisc == 0 && ip_mtudisc_timeout_q != NULL) {
                           rt_timer_queue_destroy(ip_mtudisc_timeout_q, TRUE);
                           ip_mtudisc_timeout_q = NULL;
                   }
                   return error;
           case IPCTL_ANONPORTMIN:
                   old = anonportmin;
                   error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmin);
                   if (anonportmin >= anonportmax || anonportmin > 65535
   #ifndef IPNOPRIVPORTS
                       || anonportmin < IPPORT_RESERVED
   #endif
                       ) {
                           anonportmin = old;
                           return (EINVAL);
                   }
                   return (error);
           case IPCTL_ANONPORTMAX:
                   old = anonportmax;
                   error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmax);
                   if (anonportmin >= anonportmax || anonportmax > 65535
   #ifndef IPNOPRIVPORTS
                       || anonportmax < IPPORT_RESERVED
   #endif
                       ) {
                           anonportmax = old;
                           return (EINVAL);
                   }
                   return (error);
           case IPCTL_MTUDISCTIMEOUT:
                   error = sysctl_int(oldp, oldlenp, newp, newlen,
                      &ip_mtudisc_timeout);
                   if (ip_mtudisc_timeout_q != NULL)
                           rt_timer_queue_change(ip_mtudisc_timeout_q,
                                                 ip_mtudisc_timeout);
                   return (error);
         default:          default:
                 return (EOPNOTSUPP);                  return (EOPNOTSUPP);
         }          }

Legend:
Removed from v.1.30  
changed lines
  Added in v.1.62

CVSweb <webmaster@jp.NetBSD.org>