免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2316 | 回复: 8
打印 上一主题 下一主题

[OpenBSD] pf做nat求救!!! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-02-19 19:08 |只看该作者 |倒序浏览
我用openbsd3.8和自带的pf做nat带动200台机器上网。怎么过一段时间就会进入ddb模式?上网断了-》重启。请大虾帮忙。
uvm_fault(0xd0291580, 0xdee80000, 0, 1) -> e
kernel: page fault trap, code = 0
stopped at bcopy+0x1a: repe movsl (%esi), %es%edi)
ddb>

论坛徽章:
1
寅虎
日期:2013-09-29 23:15:15
2 [报告]
发表于 2006-02-19 23:55 |只看该作者
内存问题?

论坛徽章:
0
3 [报告]
发表于 2006-02-20 07:48 |只看该作者
机器硬件没问题。装其他系统是好的。

论坛徽章:
0
4 [报告]
发表于 2006-02-20 09:09 |只看该作者
原帖由 startopenbsd 于 2006-2-20 07:48 发表
机器硬件没问题。装其他系统是好的。



如果果真硬件没问题,那就是系统配置的问题,再不然就只能是所说的“人品问题”了。因为别人的都没问题。

论坛徽章:
0
5 [报告]
发表于 2006-02-20 10:38 |只看该作者
我好像出过类似的。
在实行带宽和连接数控制的情况下,有时候会打不开网页,但会快就好。

论坛徽章:
0
6 [报告]
发表于 2006-02-20 20:19 |只看该作者
原帖由 llzqq 于 2006-2-20 09:09 发表



如果果真硬件没问题,那就是系统配置的问题,再不然就只能是所说的“人品问题”了。因为别人的都没问题。

我在网上找到一篇类似问题的文章。不过我用的是3.8,而且外网连接用的是lan。
------------------------
前段时间用新装的OpenBSD(3.7 Stable)做家里的NAT,使用Kernel Mode 的 PPPoE连接到电信的ADSL,结果系统在大流量的时候内核会crash,经过几天的调试,终于找到了Bug 所在,现在问题已经解决,并且工作非常良好。

这是crash时的信息:

uvm_fault(0xd0291580, 0xdee80000, 0, 1) -> e
kernel: page fault trap, code = 0
stopped at bcopy+0x1a: repe movsl (%esi), %es%edi)
ddb>

经过长时间的调试找到问题是出在/sys/net/if_spppsubr.c中,相关的代码如下:

sppp_input(struct ifnet *ifp,struct mbuf *m) 中的

      struct ppp_header *h, ht;

      if (sp->pp_flags & PP_NOFRAMING) {
              memcpy(&ht.protocol, mtod(m, void *), 2);
              m_adj(m, 2);
              ht.control = PPP_UI;
              ht.address = PPP_ALLSTATIONS;
              h = &ht;
      } else {
              /* Get PPP header. */
              h = mtod (m, struct ppp_header*);
              m_adj (m, PPP_HEADER_LEN);
      }

      .....

              switch (ntohs (h->protocol)) {
              default:
                      if (sp->state[IDX_LCP] == STATE_OPENED)
                              sppp_cp_send (sp, PPP_LCP, PROTO_REJ,
                                      ++sp->pp_seq, m->m_pkthdr.len + 2,
                                      &h->protocol);

  在 sppp_cp_send 函数中有一个 bcopy 调用:
      if (len)
              bcopy (data, lh+1, len);

  当 (sp->pp_flags & PP_NOFRAMING) 为真时, *h 将指向 ht (即结构
ppp_header), 接下来当调用 sppp_cp_send(sp, PPP_LCP, PROTO_REJ,
++sp->pp_seq, m->m_pkthdr.len + 2, &h->protocol) 时会产生一个错误的bcopy调用,即:

      bcopy(&h->protocol, lh+1, m->m_pkthdr.len + 2)

  此时 &h->protocol 的有效内容只有 2 个字节(因为struct ppp_header只分配4个字节),而m->m_pkthdr.len + 2 将永远 >= 2,所以此时将会出现非法的内存访问,因而就可能造成kernel crash。

  修复这个bug只要将m->m_pkthdr.len + 2,改为 2 便可,下面是这一简单的修复方法:

  将:
                      if (sp->state[IDX_LCP] == STATE_OPENED)
                              sppp_cp_send (sp, PPP_LCP, PROTO_REJ,
                                      ++sp->pp_seq, m->m_pkthdr.len + 2,
                                      &h->protocol);
  改为:
                      if (sp->state[IDX_LCP] == STATE_OPENED)
                     {
                           if (sp->pp_flags & PP_NOFRAMING)
                              sppp_cp_send (sp, PPP_LCP, PROTO_REJ,
                                      ++sp->pp_seq, 2,
                                      &h->protocol);
                           else
                              sppp_cp_send (sp, PPP_LCP, PROTO_REJ,
                                      ++sp->pp_seq, m->m_pkthdr.len + 2,
                                      &h->protocol);
                     }


  另外,我看了一下netbsd的内核级PPPoE实现,好像也存在同样的问题,代码同样在 /sys/net/if_spppsubr.c (Revision: 1.85):

                      u_int16_t prot = htons(protocol);
                      sppp_cp_send(sp, PPP_LCP, PROTO_REJ,
                          ++sp->pp_seq[IDX_LCP], m->m_pkthdr.len + 2,
                          &prot);

  不过由于我这边没有测试环境,所以无法证实这个问题,希望有测试环境的朋友帮忙测试一下。

  我将这个问题提交给了openbsd的开发者,Can Erkin Acar 提供了一个src patch,我在机器上经过长时间的测试,在使用这个patch后没有再出现crash的情况,Can Erkin Acar已经将其提交到openbsd-current中(if_spppsubr.c revision 1.36) ^_^,后附Can Erkin Acar提供的Patch,希望对你有用:

Index: if_spppsubr.c
===================================================================
RCS file: /cvs/src/sys/net/if_spppsubr.c,v
retrieving revision 1.35
diff -u -p -u -p -r1.35 if_spppsubr.c
--- if_spppsubr.c       3 Aug 2005 21:50:21 -0000       1.35
+++ if_spppsubr.c       9 Aug 2005 06:09:20 -0000
@@ -458,6 +458,7 @@ sppp_input(struct ifnet *ifp, struct mbu
      struct ifqueue *inq = 0;
      struct sppp *sp = (struct sppp *)ifp;
      struct timeval tv;
+       void *prej;
      int debug = ifp->if_flags & IFF_DEBUG;
      int s;

@@ -483,7 +484,8 @@ sppp_input(struct ifnet *ifp, struct mbu
      }

      if (sp->pp_flags & PP_NOFRAMING) {
-               memcpy(&ht.protocol, mtod(m, void *), 2);
+               prej = mtod(m, void *);
+               memcpy(&ht.protocol, prej, sizeof(ht.protocol));
              m_adj(m, 2);
              ht.control = PPP_UI;
              ht.address = PPP_ALLSTATIONS;
@@ -491,6 +493,7 @@ sppp_input(struct ifnet *ifp, struct mbu
      } else {
              /* Get PPP header. */
              h = mtod (m, struct ppp_header*);
+               prej = &h->protocol;
              m_adj (m, PPP_HEADER_LEN);
      }

@@ -511,8 +514,7 @@ sppp_input(struct ifnet *ifp, struct mbu
              default:
                      if (sp->state[IDX_LCP] == STATE_OPENED)
                              sppp_cp_send (sp, PPP_LCP, PROTO_REJ,
-                                       ++sp->pp_seq, m->m_pkthdr.len + 2,
-                                       &h->protocol);
+                                   ++sp->pp_seq, m->m_pkthdr.len + 2, prej);

----------------------------------

论坛徽章:
0
7 [报告]
发表于 2006-02-23 07:43 |只看该作者
请高手帮忙阿。

论坛徽章:
0
8 [报告]
发表于 2006-03-01 08:08 |只看该作者
大家都没有碰到过这个问题吗?

论坛徽章:
0
9 [报告]
发表于 2006-03-01 13:03 |只看该作者
我的是fb54,fb60,静态IP,有带宽优先级控制,带两百多台机,不定期重启
http://bbs.chinaunix.net/viewthread.php?tid=708855&extra=page%3D1
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP