[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.256.6.1 and 1.268.2.3

version 1.256.6.1, 2008/01/02 21:57:21 version 1.268.2.3, 2009/07/18 14:53:25
Line 45 
Line 45 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    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   * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Line 101 
Line 94 
 __KERNEL_RCSID(0, "$NetBSD$");  __KERNEL_RCSID(0, "$NetBSD$");
   
 #include "opt_inet.h"  #include "opt_inet.h"
   #include "opt_compat_netbsd.h"
 #include "opt_gateway.h"  #include "opt_gateway.h"
 #include "opt_pfil_hooks.h"  #include "opt_pfil_hooks.h"
 #include "opt_ipsec.h"  #include "opt_ipsec.h"
Line 135  __KERNEL_RCSID(0, "$NetBSD$");
Line 129  __KERNEL_RCSID(0, "$NetBSD$");
 #include <netinet/in_proto.h>  #include <netinet/in_proto.h>
 #include <netinet/in_var.h>  #include <netinet/in_var.h>
 #include <netinet/ip_var.h>  #include <netinet/ip_var.h>
   #include <netinet/ip_private.h>
 #include <netinet/ip_icmp.h>  #include <netinet/ip_icmp.h>
 /* just for gif_ttl */  /* just for gif_ttl */
 #include <netinet/in_gif.h>  #include <netinet/in_gif.h>
Line 148  __KERNEL_RCSID(0, "$NetBSD$");
Line 143  __KERNEL_RCSID(0, "$NetBSD$");
   
 #ifdef IPSEC  #ifdef IPSEC
 #include <netinet6/ipsec.h>  #include <netinet6/ipsec.h>
   #include <netinet6/ipsec_private.h>
 #include <netkey/key.h>  #include <netkey/key.h>
 #endif  #endif
 #ifdef FAST_IPSEC  #ifdef FAST_IPSEC
Line 178  __KERNEL_RCSID(0, "$NetBSD$");
Line 174  __KERNEL_RCSID(0, "$NetBSD$");
 #define IPMTUDISCTIMEOUT (10 * 60)      /* as per RFC 1191 */  #define IPMTUDISCTIMEOUT (10 * 60)      /* as per RFC 1191 */
 #endif  #endif
   
   #ifdef COMPAT_50
   #include <compat/sys/time.h>
   #include <compat/sys/socket.h>
   #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 230  u_long in_multihash;    /* size of hash 
Line 231  u_long in_multihash;    /* size of hash 
 int     in_multientries;                        /* total number of addrs */  int     in_multientries;                        /* total number of addrs */
 struct  in_multihashhead *in_multihashtbl;  struct  in_multihashhead *in_multihashtbl;
 struct  ifqueue ipintrq;  struct  ifqueue ipintrq;
 struct  ipstat  ipstat;  
 uint16_t ip_id;  uint16_t ip_id;
   
   percpu_t *ipstat_percpu;
   
 #ifdef PFIL_HOOKS  #ifdef PFIL_HOOKS
 struct pfil_head inet_pfil_hook;  struct pfil_head inet_pfil_hook;
 #endif  #endif
Line 334  do {         \
Line 336  do {         \
   
 #define IPQ_UNLOCK()            ipq_unlock()  #define IPQ_UNLOCK()            ipq_unlock()
   
 POOL_INIT(inmulti_pool, sizeof(struct in_multi), 0, 0, 0, "inmltpl", NULL,  struct pool inmulti_pool;
     IPL_SOFTNET);  struct pool ipqent_pool;
 POOL_INIT(ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", NULL,  
     IPL_VM);  
   
 #ifdef INET_CSUM_COUNTERS  #ifdef INET_CSUM_COUNTERS
 #include <sys/device.h>  #include <sys/device.h>
Line 403  ip_init(void)
Line 403  ip_init(void)
         const struct protosw *pr;          const struct protosw *pr;
         int i;          int i;
   
           pool_init(&inmulti_pool, sizeof(struct in_multi), 0, 0, 0, "inmltpl",
               NULL, IPL_SOFTNET);
           pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl",
               NULL, IPL_VM);
   
         pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);          pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
         if (pr == 0)          if (pr == 0)
                 panic("ip_init");                  panic("ip_init");
Line 417  ip_init(void)
Line 422  ip_init(void)
         for (i = 0; i < IPREASS_NHASH; i++)          for (i = 0; i < IPREASS_NHASH; i++)
                 LIST_INIT(&ipq[i]);                  LIST_INIT(&ipq[i]);
   
           ip_initid();
         ip_id = time_second & 0xfffff;          ip_id = time_second & 0xfffff;
   
         ipintrq.ifq_maxlen = ipqmaxlen;          ipintrq.ifq_maxlen = ipqmaxlen;
         ip_nmbclusters_changed();          ip_nmbclusters_changed();
   
         TAILQ_INIT(&in_ifaddrhead);          TAILQ_INIT(&in_ifaddrhead);
         in_ifaddrhashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, M_IFADDR,          in_ifaddrhashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, true,
             M_WAITOK, &in_ifaddrhash);              &in_ifaddrhash);
         in_multihashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, M_IPMADDR,          in_multihashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, true,
             M_WAITOK, &in_multihash);              &in_multihash);
         ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout);          ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout);
 #ifdef GATEWAY  #ifdef GATEWAY
         ipflow_init(ip_hashsize);          ipflow_init(ip_hashsize);
Line 446  ip_init(void)
Line 452  ip_init(void)
         MOWNER_ATTACH(&ip_tx_mowner);          MOWNER_ATTACH(&ip_tx_mowner);
         MOWNER_ATTACH(&ip_rx_mowner);          MOWNER_ATTACH(&ip_rx_mowner);
 #endif /* MBUFTRACE */  #endif /* MBUFTRACE */
   
           ipstat_percpu = percpu_alloc(sizeof(uint64_t) * IP_NSTATS);
 }  }
   
 struct  sockaddr_in ipaddr = {  struct  sockaddr_in ipaddr = {
Line 463  ipintr(void)
Line 471  ipintr(void)
         int s;          int s;
         struct mbuf *m;          struct mbuf *m;
   
           mutex_enter(softnet_lock);
           KERNEL_LOCK(1, NULL);
         while (!IF_IS_EMPTY(&ipintrq)) {          while (!IF_IS_EMPTY(&ipintrq)) {
                 s = splnet();                  s = splnet();
                 IF_DEQUEUE(&ipintrq, m);                  IF_DEQUEUE(&ipintrq, m);
                 splx(s);                  splx(s);
                 if (m == 0)                  if (m == NULL)
                         return;                          break;
                 ip_input(m);                  ip_input(m);
         }          }
           KERNEL_UNLOCK_ONE(NULL);
           mutex_exit(softnet_lock);
 }  }
   
 /*  /*
Line 510  ip_input(struct mbuf *m)
Line 522  ip_input(struct mbuf *m)
          */           */
         if (TAILQ_FIRST(&in_ifaddrhead) == 0)          if (TAILQ_FIRST(&in_ifaddrhead) == 0)
                 goto bad;                  goto bad;
         ipstat.ips_total++;          IP_STATINC(IP_STAT_TOTAL);
         /*          /*
          * If the IP header is not aligned, slurp it up into a new           * If the IP header is not aligned, slurp it up into a new
          * mbuf with space for link headers, in the event we forward           * mbuf with space for link headers, in the event we forward
Line 521  ip_input(struct mbuf *m)
Line 533  ip_input(struct mbuf *m)
                 if ((m = m_copyup(m, sizeof(struct ip),                  if ((m = m_copyup(m, sizeof(struct ip),
                                   (max_linkhdr + 3) & ~3)) == NULL) {                                    (max_linkhdr + 3) & ~3)) == NULL) {
                         /* XXXJRT new stat, please */                          /* XXXJRT new stat, please */
                         ipstat.ips_toosmall++;                          IP_STATINC(IP_STAT_TOOSMALL);
                         return;                          return;
                 }                  }
         } else if (__predict_false(m->m_len < sizeof (struct ip))) {          } else if (__predict_false(m->m_len < sizeof (struct ip))) {
                 if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {                  if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
                         ipstat.ips_toosmall++;                          IP_STATINC(IP_STAT_TOOSMALL);
                         return;                          return;
                 }                  }
         }          }
         ip = mtod(m, struct ip *);          ip = mtod(m, struct ip *);
         if (ip->ip_v != IPVERSION) {          if (ip->ip_v != IPVERSION) {
                 ipstat.ips_badvers++;                  IP_STATINC(IP_STAT_BADVERS);
                 goto bad;                  goto bad;
         }          }
         hlen = ip->ip_hl << 2;          hlen = ip->ip_hl << 2;
         if (hlen < sizeof(struct ip)) { /* minimum header length */          if (hlen < sizeof(struct ip)) { /* minimum header length */
                 ipstat.ips_badhlen++;                  IP_STATINC(IP_STAT_BADHLEN);
                 goto bad;                  goto bad;
         }          }
         if (hlen > m->m_len) {          if (hlen > m->m_len) {
                 if ((m = m_pullup(m, hlen)) == 0) {                  if ((m = m_pullup(m, hlen)) == 0) {
                         ipstat.ips_badhlen++;                          IP_STATINC(IP_STAT_BADHLEN);
                         return;                          return;
                 }                  }
                 ip = mtod(m, struct ip *);                  ip = mtod(m, struct ip *);
Line 553  ip_input(struct mbuf *m)
Line 565  ip_input(struct mbuf *m)
          * not allowed.           * not allowed.
          */           */
         if (IN_MULTICAST(ip->ip_src.s_addr)) {          if (IN_MULTICAST(ip->ip_src.s_addr)) {
                 ipstat.ips_badaddr++;                  IP_STATINC(IP_STAT_BADADDR);
                 goto bad;                  goto bad;
         }          }
   
Line 561  ip_input(struct mbuf *m)
Line 573  ip_input(struct mbuf *m)
         if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||          if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
             (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {              (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
                 if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {                  if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
                         ipstat.ips_badaddr++;                          IP_STATINC(IP_STAT_BADADDR);
                         goto bad;                          goto bad;
                 }                  }
         }          }
Line 599  ip_input(struct mbuf *m)
Line 611  ip_input(struct mbuf *m)
          * Check for additional length bogosity           * Check for additional length bogosity
          */           */
         if (len < hlen) {          if (len < hlen) {
                 ipstat.ips_badlen++;                  IP_STATINC(IP_STAT_BADLEN);
                 goto bad;                  goto bad;
         }          }
   
Line 610  ip_input(struct mbuf *m)
Line 622  ip_input(struct mbuf *m)
          * Drop packet if shorter than we expect.           * Drop packet if shorter than we expect.
          */           */
         if (m->m_pkthdr.len < len) {          if (m->m_pkthdr.len < len) {
                 ipstat.ips_tooshort++;                  IP_STATINC(IP_STAT_TOOSHORT);
                 goto bad;                  goto bad;
         }          }
         if (m->m_pkthdr.len > len) {          if (m->m_pkthdr.len > len) {
Line 779  ip_input(struct mbuf *m)
Line 791  ip_input(struct mbuf *m)
                          * ip_output().)                           * ip_output().)
                          */                           */
                         if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {                          if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) {
                                 ipstat.ips_cantforward++;                                  IP_STATINC(IP_STAT_CANTFORWARD);
                                 m_freem(m);                                  m_freem(m);
                                 return;                                  return;
                         }                          }
Line 791  ip_input(struct mbuf *m)
Line 803  ip_input(struct mbuf *m)
                          */                           */
                         if (ip->ip_p == IPPROTO_IGMP)                          if (ip->ip_p == IPPROTO_IGMP)
                                 goto ours;                                  goto ours;
                         ipstat.ips_forward++;                          IP_STATINC(IP_STAT_CANTFORWARD);
                 }                  }
 #endif  #endif
                 /*                  /*
Line 800  ip_input(struct mbuf *m)
Line 812  ip_input(struct mbuf *m)
                  */                   */
                 IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);                  IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm);
                 if (inm == NULL) {                  if (inm == NULL) {
                         ipstat.ips_cantforward++;                          IP_STATINC(IP_STAT_CANTFORWARD);
                         m_freem(m);                          m_freem(m);
                         return;                          return;
                 }                  }
Line 814  ip_input(struct mbuf *m)
Line 826  ip_input(struct mbuf *m)
          * Not for us; forward if possible and desirable.           * Not for us; forward if possible and desirable.
          */           */
         if (ipforwarding == 0) {          if (ipforwarding == 0) {
                 ipstat.ips_cantforward++;                  IP_STATINC(IP_STAT_CANTFORWARD);
                 m_freem(m);                  m_freem(m);
         } else {          } else {
                 /*                  /*
Line 825  ip_input(struct mbuf *m)
Line 837  ip_input(struct mbuf *m)
                  */                   */
                 if (downmatch) {                  if (downmatch) {
                         icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);                          icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
                         ipstat.ips_cantforward++;                          IP_STATINC(IP_STAT_CANTFORWARD);
                         return;                          return;
                 }                  }
 #ifdef IPSEC  #ifdef IPSEC
                 if (ipsec4_in_reject(m, NULL)) {                  if (ipsec4_in_reject(m, NULL)) {
                         ipsecstat.in_polvio++;                          IPSEC_STATINC(IPSEC_STAT_IN_POLVIO);
                         goto bad;                          goto bad;
                 }                  }
 #endif  #endif
Line 858  ip_input(struct mbuf *m)
Line 870  ip_input(struct mbuf *m)
                 KEY_FREESP(&sp);                  KEY_FREESP(&sp);
                 splx(s);                  splx(s);
                 if (error) {                  if (error) {
                         ipstat.ips_cantforward++;                          IP_STATINC(IP_STAT_CANTFORWARD);
                         goto bad;                          goto bad;
                 }                  }
   
Line 905  ours:
Line 917  ours:
                  */                   */
                 off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;                  off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
                 if ((off > 0 ? off + hlen : len) < IP_MINFRAGSIZE - 1) {                  if ((off > 0 ? off + hlen : len) < IP_MINFRAGSIZE - 1) {
                         ipstat.ips_badfrags++;                          IP_STATINC(IP_STAT_BADFRAGS);
                         goto bad;                          goto bad;
                 }                  }
                 /*                  /*
Line 924  ours:
Line 936  ours:
                                  * fragments.                                   * fragments.
                                  */                                   */
                                 if (ip->ip_tos != fp->ipq_tos) {                                  if (ip->ip_tos != fp->ipq_tos) {
                                         ipstat.ips_badfrags++;                                          IP_STATINC(IP_STAT_BADFRAGS);
                                           IPQ_UNLOCK();
                                         goto bad;                                          goto bad;
                                 }                                  }
                                 goto found;                                  goto found;
Line 947  found:
Line 960  found:
                          */                           */
                         if (ntohs(ip->ip_len) == 0 ||                          if (ntohs(ip->ip_len) == 0 ||
                             (ntohs(ip->ip_len) & 0x7) != 0) {                              (ntohs(ip->ip_len) & 0x7) != 0) {
                                 ipstat.ips_badfrags++;                                  IP_STATINC(IP_STAT_BADFRAGS);
                                 IPQ_UNLOCK();                                  IPQ_UNLOCK();
                                 goto bad;                                  goto bad;
                         }                          }
Line 960  found:
Line 973  found:
                  * attempt reassembly; if it succeeds, proceed.                   * attempt reassembly; if it succeeds, proceed.
                  */                   */
                 if (mff || ip->ip_off != htons(0)) {                  if (mff || ip->ip_off != htons(0)) {
                         ipstat.ips_fragments++;                          IP_STATINC(IP_STAT_FRAGMENTS);
                         s = splvm();                          s = splvm();
                         ipqe = pool_get(&ipqent_pool, PR_NOWAIT);                          ipqe = pool_get(&ipqent_pool, PR_NOWAIT);
                         splx(s);                          splx(s);
                         if (ipqe == NULL) {                          if (ipqe == NULL) {
                                 ipstat.ips_rcvmemdrop++;                                  IP_STATINC(IP_STAT_RCVMEMDROP);
                                 IPQ_UNLOCK();                                  IPQ_UNLOCK();
                                 goto bad;                                  goto bad;
                         }                          }
Line 977  found:
Line 990  found:
                                 IPQ_UNLOCK();                                  IPQ_UNLOCK();
                                 return;                                  return;
                         }                          }
                         ipstat.ips_reassembled++;                          IP_STATINC(IP_STAT_REASSEMBLED);
                         ip = mtod(m, struct ip *);                          ip = mtod(m, struct ip *);
                         hlen = ip->ip_hl << 2;                          hlen = ip->ip_hl << 2;
                         ip->ip_len = htons(ntohs(ip->ip_len) + hlen);                          ip->ip_len = htons(ntohs(ip->ip_len) + hlen);
Line 995  found:
Line 1008  found:
          */           */
         if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 &&          if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0 &&
             ipsec4_in_reject(m, NULL)) {              ipsec4_in_reject(m, NULL)) {
                 ipsecstat.in_polvio++;                  IPSEC_STATINC(IPSEC_STAT_IN_POLVIO);
                 goto bad;                  goto bad;
         }          }
 #endif  #endif
Line 1045  DPRINTF(("ip_input: no SP, packet discar
Line 1058  DPRINTF(("ip_input: no SP, packet discar
         if (ia && ip)          if (ia && ip)
                 ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len);                  ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len);
 #endif  #endif
         ipstat.ips_delivered++;          IP_STATINC(IP_STAT_DELIVERED);
     {      {
         int off = hlen, nh = ip->ip_p;          int off = hlen, nh = ip->ip_p;
   
Line 1057  bad:
Line 1070  bad:
         return;          return;
   
 badcsum:  badcsum:
         ipstat.ips_badsum++;          IP_STATINC(IP_STAT_BADSUM);
         m_freem(m);          m_freem(m);
 }  }
   
Line 1115  ip_reass(struct ipqent *ipqe, struct ipq
Line 1128  ip_reass(struct ipqent *ipqe, struct ipq
                 else if (ip_nfragpackets >= ip_maxfragpackets)                  else if (ip_nfragpackets >= ip_maxfragpackets)
                         goto dropfrag;                          goto dropfrag;
                 ip_nfragpackets++;                  ip_nfragpackets++;
                 MALLOC(fp, struct ipq *, sizeof (struct ipq),                  fp = malloc(sizeof (struct ipq), M_FTABLE, M_NOWAIT);
                     M_FTABLE, M_NOWAIT);  
                 if (fp == NULL)                  if (fp == NULL)
                         goto dropfrag;                          goto dropfrag;
                 LIST_INSERT_HEAD(ipqhead, fp, ipq_q);                  LIST_INSERT_HEAD(ipqhead, fp, ipq_q);
Line 1215  insert:
Line 1227  insert:
         q = TAILQ_FIRST(&fp->ipq_fragq);          q = TAILQ_FIRST(&fp->ipq_fragq);
         ip = q->ipqe_ip;          ip = q->ipqe_ip;
         if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {          if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) {
                 ipstat.ips_toolong++;                  IP_STATINC(IP_STAT_TOOLONG);
                 ip_freef(fp);                  ip_freef(fp);
                 return (0);                  return (0);
         }          }
Line 1247  insert:
Line 1259  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);
         FREE(fp, M_FTABLE);          free(fp, M_FTABLE);
         ip_nfragpackets--;          ip_nfragpackets--;
         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);
Line 1265  dropfrag:
Line 1277  dropfrag:
         if (fp != 0)          if (fp != 0)
                 fp->ipq_nfrags--;                  fp->ipq_nfrags--;
         ip_nfrags--;          ip_nfrags--;
         ipstat.ips_fragdropped++;          IP_STATINC(IP_STAT_FRAGDROPPED);
         m_freem(m);          m_freem(m);
         s = splvm();          s = splvm();
         pool_put(&ipqent_pool, ipqe);          pool_put(&ipqent_pool, ipqe);
Line 1300  ip_freef(struct ipq *fp)
Line 1312  ip_freef(struct ipq *fp)
             printf("ip_freef: nfrags %d != %d\n", fp->ipq_nfrags, nfrags);              printf("ip_freef: nfrags %d != %d\n", fp->ipq_nfrags, nfrags);
         ip_nfrags -= nfrags;          ip_nfrags -= nfrags;
         LIST_REMOVE(fp, ipq_q);          LIST_REMOVE(fp, ipq_q);
         FREE(fp, M_FTABLE);          free(fp, M_FTABLE);
         ip_nfragpackets--;          ip_nfragpackets--;
 }  }
   
Line 1332  ip_reass_ttl_decr(u_int ticks)
Line 1344  ip_reass_ttl_decr(u_int ticks)
                                        0 : fp->ipq_ttl - ticks);                                         0 : fp->ipq_ttl - ticks);
                         nfp = LIST_NEXT(fp, ipq_q);                          nfp = LIST_NEXT(fp, ipq_q);
                         if (fp->ipq_ttl == 0) {                          if (fp->ipq_ttl == 0) {
                                 ipstat.ips_fragtimeout++;                                  IP_STATINC(IP_STAT_FRAGTIMEOUT);
                                 ip_freef(fp);                                  ip_freef(fp);
                         } else {                          } else {
                                 nfrags += fp->ipq_nfrags;                                  nfrags += fp->ipq_nfrags;
Line 1383  ip_slowtimo(void)
Line 1395  ip_slowtimo(void)
         static u_int dropscanidx = 0;          static u_int dropscanidx = 0;
         u_int i;          u_int i;
         u_int median_ttl;          u_int median_ttl;
         int s = splsoftnet();  
           mutex_enter(softnet_lock);
           KERNEL_LOCK(1, NULL);
   
         IPQ_LOCK();          IPQ_LOCK();
   
Line 1425  ip_slowtimo(void)
Line 1439  ip_slowtimo(void)
                 dropscanidx = i;                  dropscanidx = i;
         }          }
         IPQ_UNLOCK();          IPQ_UNLOCK();
         splx(s);  
           KERNEL_UNLOCK_ONE(NULL);
           mutex_exit(softnet_lock);
 }  }
   
 /*  /*
  * Drain off all datagram fragments.   * Drain off all datagram fragments.  Don't acquire softnet_lock as
    * can be called from hardware interrupt context.
  */   */
 void  void
 ip_drain(void)  ip_drain(void)
 {  {
   
           KERNEL_LOCK(1, NULL);
   
         /*          /*
          * We may be called from a device's interrupt context.  If           * We may be called from a device's interrupt context.  If
          * the ipq is already busy, just bail out now.           * the ipq is already busy, just bail out now.
          */           */
         if (ipq_lock_try() == 0)          if (ipq_lock_try() != 0) {
                 return;                  /*
                    * Drop half the total fragments now. If more mbufs are
         /*                   * needed, we will be called again soon.
          * Drop half the total fragments now. If more mbufs are needed,                   */
          *  we will be called again soon.                  ip_reass_drophalf();
          */                  IPQ_UNLOCK();
         ip_reass_drophalf();          }
   
         IPQ_UNLOCK();          KERNEL_UNLOCK_ONE(NULL);
 }  }
   
 /*  /*
Line 1543  ip_dooptions(struct mbuf *m)
Line 1562  ip_dooptions(struct mbuf *m)
                         /*                          /*
                          * locate outgoing interface                           * locate outgoing interface
                          */                           */
                         bcopy((void *)(cp + off), (void *)&ipaddr.sin_addr,                          memcpy((void *)&ipaddr.sin_addr, (void *)(cp + off),
                             sizeof(ipaddr.sin_addr));                              sizeof(ipaddr.sin_addr));
                         if (opt == IPOPT_SSRR)                          if (opt == IPOPT_SSRR)
                                 ia = ifatoia(ifa_ifwithladdr(sintosa(&ipaddr)));                                  ia = ifatoia(ifa_ifwithladdr(sintosa(&ipaddr)));
Line 1579  ip_dooptions(struct mbuf *m)
Line 1598  ip_dooptions(struct mbuf *m)
                         off--;                  /* 0 origin */                          off--;                  /* 0 origin */
                         if ((off + sizeof(struct in_addr)) > optlen)                          if ((off + sizeof(struct in_addr)) > optlen)
                                 break;                                  break;
                         bcopy((void *)(&ip->ip_dst), (void *)&ipaddr.sin_addr,                          memcpy((void *)&ipaddr.sin_addr, (void *)(&ip->ip_dst),
                             sizeof(ipaddr.sin_addr));                              sizeof(ipaddr.sin_addr));
                         /*                          /*
                          * locate outgoing interface; if we're the destination,                           * locate outgoing interface; if we're the destination,
Line 1646  ip_dooptions(struct mbuf *m)
Line 1665  ip_dooptions(struct mbuf *m)
                                             (u_char *)ip;                                              (u_char *)ip;
                                         goto bad;                                          goto bad;
                                 }                                  }
                                 bcopy(cp0, &ipaddr.sin_addr,                                  memcpy(&ipaddr.sin_addr, cp0,
                                     sizeof(struct in_addr));                                      sizeof(struct in_addr));
                                 if (ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)))                                  if (ifatoia(ifa_ifwithaddr(sintosa(&ipaddr)))
                                     == NULL)                                      == NULL)
Line 1679  ip_dooptions(struct mbuf *m)
Line 1698  ip_dooptions(struct mbuf *m)
         return (0);          return (0);
 bad:  bad:
         icmp_error(m, type, code, 0, 0);          icmp_error(m, type, code, 0, 0);
         ipstat.ips_badoptions++;          IP_STATINC(IP_STAT_BADOPTIONS);
         return (1);          return (1);
 }  }
   
Line 1720  save_rte(u_char *option, struct in_addr 
Line 1739  save_rte(u_char *option, struct in_addr 
 #endif /* 0 */  #endif /* 0 */
         if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))          if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst)))
                 return;                  return;
         bcopy((void *)option, (void *)ip_srcrt.srcopt, olen);          memcpy((void *)ip_srcrt.srcopt, (void *)option, olen);
         ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);          ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr);
         ip_srcrt.dst = dst;          ip_srcrt.dst = dst;
 }  }
Line 1852  ip_forward(struct mbuf *m, int srcrt)
Line 1871  ip_forward(struct mbuf *m, int srcrt)
         }          }
 #endif  #endif
         if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {          if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {
                 ipstat.ips_cantforward++;                  IP_STATINC(IP_STAT_CANTFORWARD);
                 m_freem(m);                  m_freem(m);
                 return;                  return;
         }          }
Line 1916  ip_forward(struct mbuf *m, int srcrt)
Line 1935  ip_forward(struct mbuf *m, int srcrt)
             (struct ip_moptions *)NULL, (struct socket *)NULL);              (struct ip_moptions *)NULL, (struct socket *)NULL);
   
         if (error)          if (error)
                 ipstat.ips_cantforward++;                  IP_STATINC(IP_STAT_CANTFORWARD);
         else {          else {
                 ipstat.ips_forward++;                  uint64_t *ips = IP_STAT_GETREF();
                 if (type)                  ips[IP_STAT_FORWARD]++;
                         ipstat.ips_redirectsent++;                  if (type) {
                 else {                          ips[IP_STAT_REDIRECTSENT]++;
                           IP_STAT_PUTREF();
                   } else {
                           IP_STAT_PUTREF();
                         if (mcopy) {                          if (mcopy) {
 #ifdef GATEWAY  #ifdef GATEWAY
                                 if (mcopy->m_flags & M_CANFASTFWD)                                  if (mcopy->m_flags & M_CANFASTFWD)
Line 1953  ip_forward(struct mbuf *m, int srcrt)
Line 1975  ip_forward(struct mbuf *m, int srcrt)
         case EMSGSIZE:          case EMSGSIZE:
                 type = ICMP_UNREACH;                  type = ICMP_UNREACH;
                 code = ICMP_UNREACH_NEEDFRAG;                  code = ICMP_UNREACH_NEEDFRAG;
 #if !defined(IPSEC) && !defined(FAST_IPSEC)  
                 if ((rt = rtcache_getrt(&ipforward_rt)) != NULL)                  if ((rt = rtcache_validate(&ipforward_rt)) != NULL)
                         destmtu = rt->rt_ifp->if_mtu;                          destmtu = rt->rt_ifp->if_mtu;
 #else  
                 /*  #if defined(IPSEC) || defined(FAST_IPSEC)
                  * If the packet is routed over IPsec tunnel, tell the                  {
                  * originator the tunnel MTU.                          /*
                  *      tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz                           * If the packet is routed over IPsec tunnel, tell the
                  * XXX quickhack!!!                           * originator the tunnel MTU.
                  */                           *      tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz
                 if ((rt = rtcache_getrt(&ipforward_rt)) != NULL) {                           * XXX quickhack!!!
                            */
   
                         struct secpolicy *sp;                          struct secpolicy *sp;
                         int ipsecerror;                          int ipsecerror;
                         size_t ipsechdr;                          size_t ipsechdr;
Line 1973  ip_forward(struct mbuf *m, int srcrt)
Line 1997  ip_forward(struct mbuf *m, int srcrt)
                             IPSEC_DIR_OUTBOUND, IP_FORWARDING,                              IPSEC_DIR_OUTBOUND, IP_FORWARDING,
                             &ipsecerror);                              &ipsecerror);
   
                         if (sp == NULL)                          if (sp != NULL) {
                                 destmtu = rt->rt_ifp->if_mtu;  
                         else {  
                                 /* count IPsec header size */                                  /* count IPsec header size */
                                 ipsechdr = ipsec4_hdrsiz(mcopy,                                  ipsechdr = ipsec4_hdrsiz(mcopy,
                                     IPSEC_DIR_OUTBOUND, NULL);                                      IPSEC_DIR_OUTBOUND, NULL);
Line 1989  ip_forward(struct mbuf *m, int srcrt)
Line 2011  ip_forward(struct mbuf *m, int srcrt)
                                  && sp->req->sav != NULL                                   && sp->req->sav != NULL
                                  && sp->req->sav->sah != NULL) {                                   && sp->req->sav->sah != NULL) {
                                         ro = &sp->req->sav->sah->sa_route;                                          ro = &sp->req->sav->sah->sa_route;
                                           rt = rtcache_validate(ro);
                                         if (rt && rt->rt_ifp) {                                          if (rt && rt->rt_ifp) {
                                                 destmtu =                                                  destmtu =
                                                     rt->rt_rmx.rmx_mtu ?                                                      rt->rt_rmx.rmx_mtu ?
Line 2005  ip_forward(struct mbuf *m, int srcrt)
Line 2028  ip_forward(struct mbuf *m, int srcrt)
 #endif  #endif
                         }                          }
                 }                  }
 #endif /*IPSEC*/  #endif /*defined(IPSEC) || defined(FAST_IPSEC)*/
                 ipstat.ips_cantfrag++;                  IP_STATINC(IP_STAT_CANTFRAG);
                 break;                  break;
   
         case ENOBUFS:          case ENOBUFS:
Line 2034  ip_savecontrol(struct inpcb *inp, struct
Line 2057  ip_savecontrol(struct inpcb *inp, struct
     struct mbuf *m)      struct mbuf *m)
 {  {
   
         if (inp->inp_socket->so_options & SO_TIMESTAMP) {          if (inp->inp_socket->so_options & SO_TIMESTAMP
   #ifdef SO_OTIMESTAMP
               || inp->inp_socket->so_options & SO_OTIMESTAMP
   #endif
               ) {
                 struct timeval tv;                  struct timeval tv;
   
                 microtime(&tv);                  microtime(&tv);
   #ifdef SO_OTIMESTAMP
                   if (inp->inp_socket->so_options & SO_OTIMESTAMP) {
                           struct timeval50 tv50;
                           timeval_to_timeval50(&tv, &tv50);
                           *mp = sbcreatecontrol((void *) &tv50, sizeof(tv50),
                               SCM_OTIMESTAMP, SOL_SOCKET);
                   } else
   #endif
                 *mp = sbcreatecontrol((void *) &tv, sizeof(tv),                  *mp = sbcreatecontrol((void *) &tv, sizeof(tv),
                     SCM_TIMESTAMP, SOL_SOCKET);                      SCM_TIMESTAMP, SOL_SOCKET);
                 if (*mp)                  if (*mp)
Line 2083  ip_savecontrol(struct inpcb *inp, struct
Line 2118  ip_savecontrol(struct inpcb *inp, struct
                 if (*mp)                  if (*mp)
                         mp = &(*mp)->m_next;                          mp = &(*mp)->m_next;
         }          }
           if (inp->inp_flags & INP_RECVTTL) {
                   *mp = sbcreatecontrol((void *) &ip->ip_ttl,
                       sizeof(uint8_t), IP_RECVTTL, IPPROTO_IP);
                   if (*mp)
                           mp = &(*mp)->m_next;
           }
 }  }
   
 /*  /*
Line 2101  sysctl_net_inet_ip_forwsrcrt(SYSCTLFN_AR
Line 2142  sysctl_net_inet_ip_forwsrcrt(SYSCTLFN_AR
         if (error || newp == NULL)          if (error || newp == NULL)
                 return (error);                  return (error);
   
         if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FORWSRCRT,          error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FORWSRCRT,
             0, NULL, NULL, NULL))              0, NULL, NULL, NULL);
                 return (EPERM);          if (error)
                   return (error);
   
         ip_forwsrcrt = tmp;          ip_forwsrcrt = tmp;
   
Line 2129  sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS
Line 2171  sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS
         if (tmp < 0)          if (tmp < 0)
                 return (EINVAL);                  return (EINVAL);
   
           mutex_enter(softnet_lock);
   
         ip_mtudisc_timeout = tmp;          ip_mtudisc_timeout = tmp;
         rt_timer_queue_change(ip_mtudisc_timeout_q, ip_mtudisc_timeout);          rt_timer_queue_change(ip_mtudisc_timeout_q, ip_mtudisc_timeout);
   
           mutex_exit(softnet_lock);
   
         return (0);          return (0);
 }  }
   
Line 2142  sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS
Line 2188  sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS
 static int  static int
 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARGS)  sysctl_net_inet_ip_maxflows(SYSCTLFN_ARGS)
 {  {
         int s;          int error;
   
         s = sysctl_lookup(SYSCTLFN_CALL(rnode));          error = sysctl_lookup(SYSCTLFN_CALL(rnode));
         if (s || newp == NULL)          if (error || newp == NULL)
                 return (s);                  return (error);
   
         s = splsoftnet();          mutex_enter(softnet_lock);
         ipflow_reap(0);          KERNEL_LOCK(1, NULL);
         splx(s);  
           ipflow_prune();
   
           KERNEL_UNLOCK_ONE(NULL);
           mutex_exit(softnet_lock);
   
         return (0);          return (0);
 }  }
Line 2172  sysctl_net_inet_ip_hashsize(SYSCTLFN_ARG
Line 2222  sysctl_net_inet_ip_hashsize(SYSCTLFN_ARG
                 /*                  /*
                  * Can only fail due to malloc()                   * Can only fail due to malloc()
                  */                   */
                 if (ipflow_invalidate_all(tmp))                  mutex_enter(softnet_lock);
                         return ENOMEM;                  KERNEL_LOCK(1, NULL);
   
                   error = ipflow_invalidate_all(tmp);
   
                   KERNEL_UNLOCK_ONE(NULL);
                   mutex_exit(softnet_lock);
   
         } else {          } else {
                 /*                  /*
                  * EINVAL if not a power of 2                   * EINVAL if not a power of 2
                  */                   */
                 return EINVAL;                  error = EINVAL;
         }          }
   
         return (0);          return error;
 }  }
 #endif /* GATEWAY */  #endif /* GATEWAY */
   
   static int
   sysctl_net_inet_ip_stats(SYSCTLFN_ARGS)
   {
   
           return (NETSTAT_SYSCTL(ipstat_percpu, IP_NSTATS));
   }
   
 SYSCTL_SETUP(sysctl_net_inet_ip_setup, "sysctl net.inet.ip subtree setup")  SYSCTL_SETUP(sysctl_net_inet_ip_setup, "sysctl net.inet.ip subtree setup")
 {  {
Line 2389  SYSCTL_SETUP(sysctl_net_inet_ip_setup, "
Line 2451  SYSCTL_SETUP(sysctl_net_inet_ip_setup, "
                        CTLFLAG_PERMANENT,                         CTLFLAG_PERMANENT,
                        CTLTYPE_STRUCT, "stats",                         CTLTYPE_STRUCT, "stats",
                        SYSCTL_DESCR("IP statistics"),                         SYSCTL_DESCR("IP statistics"),
                        NULL, 0, &ipstat, sizeof(ipstat),                         sysctl_net_inet_ip_stats, 0, NULL, 0,
                        CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS,                         CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS,
                        CTL_EOL);                         CTL_EOL);
 }  }
   
   void
   ip_statinc(u_int stat)
   {
   
           KASSERT(stat < IP_NSTATS);
           IP_STATINC(stat);
   }

Legend:
Removed from v.1.256.6.1  
changed lines
  Added in v.1.268.2.3

CVSweb <webmaster@jp.NetBSD.org>