小杰的博客 http://www.kumouse.com Fri, 03 Sep 2010 12:55:48 +0000 http://wordpress.org/?v=2.9.1 en hourly 1 维修 tplink wr541G 记 http://www.kumouse.com/?p=663 http://www.kumouse.com/?p=663#comments Fri, 03 Sep 2010 12:43:35 +0000 小杰 http://www.kumouse.com/?p=663  

前几天收了两个541G,有一个不通电。看到一个电容坏了就换了,可是还是一个样,今天有空,拿出来看,用表测,发现整流后输出电压只有5V,应该空载13~15V左右,再测整流电路的前边,有4个电容,输出也是一样,再测测正常的路由,发现是这4个电容有问题,从402上拆下4个,换上一切OK了,再测测换下来的电容,两个22UF的,两个200uf以上的,我的表测不出来,其中一个200uf以上的电容断路。这种贴片的电容也能坏呀!!!

]]>
http://www.kumouse.com/?feed=rss2&p=663 0
维修 tplink 460+ 之旅 http://www.kumouse.com/?p=659 http://www.kumouse.com/?p=659#comments Wed, 01 Sep 2010 16:50:03 +0000 小杰 http://www.kumouse.com/?p=659 前几天收了一个很新tplink 460+ 路由器,白色外壳,蓝灯,很好看。

回家一试,发现有lan3能用,其它口全是坏的,十分郁闷。以为是网卡心片坏了,就放在那里有

又过了几天我又收了一个3.5版的410,要改成285.要换CPU,于是我就把这个460的CPU换了上去

发现410和460一个样。分析出原来是CPU的问题。于是,我把一个402M的CPU换到了460+上

一切OK了,所有口全能用了。写这篇博文用的就是这个刚修好的460+ 呵呵

过几天再把这个460改成285 

哈哈

 

 

]]>
http://www.kumouse.com/?feed=rss2&p=659 0
tp 460 h-jtag 成功认出CPU 与 flash 备份与擦写成功 写入失败 http://www.kumouse.com/?p=655 http://www.kumouse.com/?p=655#comments Tue, 10 Aug 2010 14:36:49 +0000 小杰 http://www.kumouse.com/?p=655 一天的工夫,备份原厂固件不行,有问题 在460上备份其它flash里的固件好像是没什么 问题 ,因为现在无法写入,所以不知道备出的怎么样呢,反正是可以认flash了,又是一次进步。上脚本

 

FLASH SECTION:
MACRONIX
MX29LV800XB
MEMORY SECTION:
8-BIT X 1-CHIP
0xFFC00000
0×0
XTAL SECTION:
NULL
TCK SECTION:
0
0
SCRIPT SECTION:
Setmem+32-Bit+0×90008008+0×00000000
Setmem+32-Bit+0×9000800C+0xFFFFFFFF
Setmem+32-Bit+0×8000C008+0×00000000
Setmem+32-Bit+0×80006000+0×20780000
Setmem+32-Bit+0×80006014+0×00004233
Setmem+32-Bit+0×80006018+0×09502845
Setmem+32-Bit+0×80006008+0×20FFFF20
Setmem+32-Bit+0×80006004+0xFFFC4285
Setmem+32-Bit+0×80006010+0×00FE42B5
PGMOPTION SECTION:
存在hfc后缀,或直接下载下边的的文件
成功上图
]]>
http://www.kumouse.com/?feed=rss2&p=655 0
TP LINK R460 jtag 正确接法 线序 主板v1.0 标签v3.1 系统内为v3.0 http://www.kumouse.com/?p=650 http://www.kumouse.com/?p=650#comments Mon, 09 Aug 2010 08:45:48 +0000 小杰 http://www.kumouse.com/?p=650 CPU           主板焊盘              定义

45                    7                      TMS

46                    5                      TDI

47                    9                      TCK

49                    13                    TDO

就是一般情况下3,5,7,9分别为TDI,TDO,TMS,TCK,现在TP做了手脚,把原来的3接到了5,把5接到了13,按我上边说的接,用h-jtag 0,92版本或以上,就可以成功读出CPU信息

]]>
http://www.kumouse.com/?feed=rss2&p=650 0
CPU飞线 焊锡多了弄不掉 结果把CPU拿下来了 用了一上午才弄回去 http://www.kumouse.com/?p=647 http://www.kumouse.com/?p=647#comments Sat, 07 Aug 2010 16:27:03 +0000 小杰 http://www.kumouse.com/?p=647 练习了如何焊高密度的心片,焊的是88e6218-lgo 下次打算试试BGA的,还是先买了锡球再说吧

]]>
http://www.kumouse.com/?feed=rss2&p=647 0
SDRAM 8位并联成16位 (目前没成功) http://www.kumouse.com/?p=640 http://www.kumouse.com/?p=640#comments Sat, 07 Aug 2010 16:11:19 +0000 小杰 http://www.kumouse.com/?p=640 原来的内存颗粒为EM638165TS-7,8M 16位

我要用两片GM72V66841CT7J来代替,这个是8位8M的,我用两片

现在的问题是我要如何接线用两片8位的,代替一片16位的

 

我用下边的方法没成功,不知道是为什么,求高手解答

我用叠焊,用一个8位的颗粒焊在原来的焊盘上,第二层的把除了数据线和DQM以外的线与第一层连在了一起.用第二层的数据线分别连第一层的4,7,10,13,51,48,45,42,进行补位,用第二层的QDM飞线到第一层的15代替LDQM.

对应关系

第一层    第二层

4                5

7                8

10             11

13              2

51              50

48              47

45              44

42              53

15              39                这个是代替LDQM

 

8位颗粒只有一个DQM,不分LDQM和UDQM,我这么接对吗?

我用这个方法代替原路由器的16位8M的内存(路由不认8位,只认16位)

可是路由无法启动,是TP 460的,正常M2闪,改完后M1 M2全不亮,插网线对应的口亮灯,ping不通,请大家教教我吧。

发现了个问题,我现在用的是32M的HY57V561620BT-H代替的,原来内存是143的,我用133的能用,8位那个是100的,可能也是出问题的地方,改天换个试试,有结果了会再发贴的.

发下这几个颗粒的PDF

GM72V66841CT

EM638165TS-7

HY57V561620B(L_S)T(Rev1.4)

]]>
http://www.kumouse.com/?feed=rss2&p=640 0
TPLINK 普联 410 460 jtag ttl 定义 (这个接法有问题,以解决见文中链接) http://www.kumouse.com/?p=636 http://www.kumouse.com/?p=636#comments Sat, 07 Aug 2010 15:29:02 +0000 小杰 http://www.kumouse.com/?p=636 TP410 460 jtag 与 ttl 的定义

我用自制的jtag线用h-jtag 0.92连接不成功,总觉得这个定义有点问题,好像少了条线到CPU,等我发现了问题出在哪里再说,这个图先留着.

jtag线制作见:http://www.kumouse.com/?p=636

正确接法见:http://www.kumose.com/?p=650

]]>
http://www.kumouse.com/?feed=rss2&p=636 0
刷路由 flash 的 jtag ttl 线的制作(简易版) http://www.kumouse.com/?p=624 http://www.kumouse.com/?p=624#comments Sat, 07 Aug 2010 15:07:01 +0000 小杰 http://www.kumouse.com/?p=624 首先要感谢我的好友 乐天 的帮助

发图:

以上是几个接线的示意图,接法基本是一样的,我也做了一条,好用,我串的是100殴的电阻。

]]>
http://www.kumouse.com/?feed=rss2&p=624 0
fedora13 安装 SpoonWep2 心得 http://www.kumouse.com/?p=621 http://www.kumouse.com/?p=621#comments Tue, 03 Aug 2010 13:25:17 +0000 小杰 http://www.kumouse.com/?p=621 今天在fedora13下破解wep,懒得总是复制MAC了,想能不能在fedora上也安装上SpoonWep2呢,找了半天也没有rpm的包.后来发现直接把deb的包解出来,把文件直接复制到系统对应目录就可以运行了,很简单嘛:) .后来又发现问题了.在shell中运行,找不到网出现这个错误 /usr/local/bin/wifispoonfeeder/spoonwep/tmp/wscapture-01.txt 在网上找找了,发现在出现这个错误时,再打开一个shell运行ln -s /usr/local/bin/wifispoonfeeder/spoonwep/tmp/wscapture-01.csv /usr/local/bin/wifispoonfeeder/spoonwep/tmp/wscapture-01.txt 命令就可以解决了,但是每次搜网都要运行一次.

spoonwep-2-1-i686.pkg.tar

]]>
http://www.kumouse.com/?feed=rss2&p=621 2
IP 分片与重组 http://www.kumouse.com/?p=619 http://www.kumouse.com/?p=619#comments Wed, 21 Jul 2010 15:43:08 +0000 小杰 http://www.kumouse.com/?p=619 IP:分片与重组

1. 引言
为了与互联网上的任意计算机通信,每个应用TCP/IP的计算机必须具有分片和重组的代码,一个设计良好的应用软件,会生成足够小的数据报,
因此主机并不需要经常执行分片任务.

2. 数据报的分片
分片发生在选择路由之后,以及放入接口队列之前.IP把数据报长度与MTU进行比较,确定是否需要分片.
如需分片,IP首先生成多个数据报,并将每个数据报中的分片位置1,将源数据报中的数据按顺序分片,并将它们装入这些数据报中.
它还在同一源数据报产生的所有数据报片中将MF位置为1,末尾片除外.IP一边分片,一边将它们传递给网络接口发送出去.

2.1 为一个数据报片再次分片
对于MF未置1的片,和上边说的没区别,除了最后一个片外,其它全置1.但对于MF为1的源片,再次分片后的所有分片MF全置1

3. 分片的实现

/* ipputp.c – ipputp */

#include <conf.h>
#include <kernel.h>
#include <network.h>

/*————————————————————————
 * ipputp  -  发送一个数据包到一个接口的输出队列
 *————————————————————————
 */
int
ipputp(unsigned ifn, IPaddr nh, struct ep *pep)
{
    struct    netif    *pni = &nif[ifn];        /* 接口指针*/
    struct    ip    *pip;                /* IP报指针*/
    int        hlen, maxdlen, tosend, offset, offindg;

    if (pni->ni_state == NIS_DOWN) {            /* 接口关闭则返回*/
        freebuf(pep);
        return SYSERR;
    }
    pip = (struct ip *)pep->ep_data;            /* IP报指向*/
    if (pip->ip_len <= pni->ni_mtu) {        /* IP报长度小于等于接口MTU,则直接发送数据报*/
        pep->ep_nexthop = nh;
        pip->ip_cksum = 0;
        iph2net(pip);
        pep->ep_order &= ~EPO_IP;
        pip->ip_cksum = cksum((WORD *)pip, IP_HLEN(pip));
        return netwrite(pni, pep, EP_HLEN+net2hs(pip->ip_len));
    }
    /* 否则,我们必须分片 */

    if (pip->ip_fragoff & IP_DF) {            /* 能否分片,不能分片则报错并返回*/
        IpFragFails++;
        icmp(ICT_DESTUR, ICC_FNADF, pip->ip_src, pep, 0);
        return OK;
    }
    maxdlen = (pni->ni_mtu – IP_HLEN(pip)) &~ 7;    /* 最大长度为MTU减去IP头长度,并增加到8的倍数*/
    offset = 0;                    /* 偏移量*/
    offindg = (pip->ip_fragoff & IP_FRAGOFF)<<3;    /* 偏移量,保存控制位*/
    tosend = pip->ip_len – IP_HLEN(pip);        /* 要发送的IP报长度,不包括IP报头*/

    while (tosend > maxdlen) {            /* 仅当剩余的数据大于可发送的最大数据量时才发送*/
        if (ipfsend(pni,nh,pep,offset,maxdlen,offindg) != OK) {    /* 生成并发送分片*/
            IpOutDiscards++;
            freebuf(pep);
            return SYSERR;
        }
        IpFragCreates++;
        tosend -= maxdlen;
        offset += maxdlen;
        offindg += maxdlen;            /* */
    }
    IpFragOKs++;
    IpFragCreates++;
    hlen = ipfhcopy(pep, pep, offindg);        /* 首部拷贝处理,返回首部长度*/
    pip = (struct ip *)pep->ep_data;            /* 取IP数据报*/
    /*处理最后一个分片,当最后剩余的数据小于等于可发送的最大数据量 */
    memcpy(&pep->ep_data[hlen], &pep->ep_data[IP_HLEN(pip)+offset],
        tosend);                    /* 修改源报,使之变为最后一个报片*/
    /*非末尾的数据报片再次分片时,保证MF全为1 */
    pip->ip_fragoff = (pip->ip_fragoff & IP_MF)|(offindg>>3);
    pip->ip_len = tosend + hlen;
    pip->ip_cksum = 0;
    iph2net(pip);
    pep->ep_order &= ~EPO_IP;
    pip->ip_cksum = cksum((WORD *)pip, hlen);
    pep->ep_nexthop = nh;
    return netwrite(pni, pep, EP_HLEN+net2hs(pip->ip_len));
}

3.1 发送一个数据报片

/* ipfsend.c – ipfsend */

#include <conf.h>
#include <kernel.h>
#include <network.h>

int ipfhcopy(struct ep *, struct ep *, unsigned);

/*————————————————————————
 *  ipfsend -  发送一个IP数据报的分片
 *————————————————————————
 */
int
ipfsend(struct netif *pni, IPaddr nexthop, struct ep *pep,
    unsigned offset, unsigned maxdlen, unsigned offindg)
{
    struct    ep    *pepnew;
    struct    ip    *pip, *pipnew;
    int        hlen, len;

    pepnew = (struct ep *)getbuf(Net.netpool);        /* 申请一个新帧的缓冲区*/
    if (pepnew == (struct ep *)SYSERR)
        return SYSERR;
    pepnew->ep_order = ~0;
    hlen = ipfhcopy(pepnew, pep, offindg);    /* 复制头 */

    pip = (struct ip *)pep->ep_data;        /* 源IP报的指向*/
    pipnew = (struct ip *)pepnew->ep_data;    /* 新生成的IP报*/
    pipnew->ip_fragoff = IP_MF | (offindg>>3);
    pipnew->ip_len = len = maxdlen + hlen;
    pipnew->ip_cksum = 0;

    iph2net(pipnew);
    pepnew->ep_order &= ~EPO_IP;        /* 清除字节顺序*/
    pipnew->ip_cksum = cksum((WORD *)pipnew, hlen);

    memcpy(&pepnew->ep_data[hlen],        /* 复制数据*/
        &pep->ep_data[IP_HLEN(pip)+offset], maxdlen);
    pepnew->ep_nexthop = nexthop;

    return netwrite(pni, pepnew, EP_HLEN+len);    /* 发送并返回 */
}

3.2 复制数据报首部

/* ipfhcopy.c – ipfhcopy */

#include <conf.h>
#include <kernel.h>
#include <network.h>

/*————————————————————————
 *  ipfhcopy -  copy the hardware, IP header, and options for a fragment
 *————————————————————————
 */
int
ipfhcopy(struct ep *pepto, struct ep *pepfrom, unsigned offindg)
{
    struct    ip    *pipfrom = (struct ip *)pepfrom->ep_data;    /* 旧IP报*/
    unsigned    i, maxhlen, olen, otype;
    unsigned    hlen = (IP_MINHLEN<<2);        /* IP头最小长度*4 ,就是以字节为单位了*/

    if (offindg == 0) {    /* 偏移为0,说明是第一个分片,复制帧的头和IP头到新的帧*/
        memcpy(pepto, pepfrom, EP_HLEN+IP_HLEN(pipfrom));
        return IP_HLEN(pipfrom);
    }
    /* 以下就说明不是第一个IP分片了*/
    memcpy(pepto, pepfrom, EP_HLEN+hlen);        /* 复制帧的头和除了IP选项外的报头*/

    /*复制选项 */

    maxhlen = IP_HLEN(pipfrom);        /* 包括选项的IP头的长度*/
    i = hlen;                /* 不包括选项的IP头长度*/
    while (i < maxhlen) {            /* 最小头比最大头小,说明有IP选项*/
        otype = pepfrom->ep_data[i];    /* IP选项*/
        olen = pepfrom->ep_data[++i];    /* 选项长度*/
        if (otype & IPO_COPY) {        /* 如果复制位为1*/
            memcpy(&pepto->ep_data[hlen],
                &pepfrom->ep_data[i-1], olen);        /* 复制这个选项到所有新的帧*/
            hlen += olen;
        } else if (otype == IPO_NOP || otype == IPO_EOOP) {    /* 选项结束或没有操作*/
            pepto->ep_data[hlen++] = otype;
            olen = 1;
        }
        i += olen-1;
        
        if (otype == IPO_EOOP)
            break;
    }
    /* pad to a multiple of 4 octets */
    while (hlen % 4)            /* 填充到4字节的整数倍*/
        pepto->ep_data[hlen++] = IPO_NOP;
    return hlen;
}

4. 数据报的重组

4.1 数据结构

/* ipreass.h */

/* Internet Protocol (IP)  reassembly support */

#define IP_FQSIZE    10    /* 分片队列的数大数量 */
#define IP_MAXNF    10    /* 分片/数据报 的最大数量 */
#define    IP_FTTL        60    /* 生存时间(秒)*/

/* ipf_state flags */

#define    IPFF_VALID    1    /* 内容是有效的 */
#define    IPFF_BOGUS    2    /* 丢弃        */
#define    IPFF_FREE    3    /* 这个队列可以自由分配    */

struct    ipfq    {
    char    ipf_state;        /* 队列状态,值为上边 3种        */
    IPaddr    ipf_src;        /* 源IP地址 */
    short    ipf_id;            /* 数据报ID */
    int    ipf_ttl;        /* 数据报重组的生存时间 */
    int    ipf_q;            /* 分片存储的链表 */
};

extern    int    ipfmutex;        /* 互斥 mutex for ipfqt[] */
extern    struct    ipfq    ipfqt[];    /* IP分片队列表        */

int ipfsend(struct netif *, IPaddr, struct ep *, unsigned, unsigned,
    unsigned);
int ipfhcopy(struct ep *, struct ep *, unsigned);

4.2 互斥操作

为了何证进程在数据报片的链表时不会互相干扰,重组程序代码使用了一个互斥信号量ipfmutex.在ipreass.h中

4.3 在链表中加入一个数据报片

/* ipreass.c – ipreass */

#include <conf.h>
#include <kernel.h>
#include <network.h>

int ipfadd(struct ipfq *, struct ep *);
struct    ep    *ipfjoin(struct ipfq *);

/*————————————————————————
 *  ipreass  -  reassemble an IP datagram, if necessary
 *    returns packet, if complete; 0 otherwise
 *  IP数据报重组,如果报片到齐则重组该包,并返回完整的数据报,否则返回0
 *————————————————————————
 */
struct ep *
ipreass(struct ep *pep)
{
    struct    ep    *pep2;
    struct    ip    *pip;
    int        firstfree;
    int        i;

    pip = (struct ip *)pep->ep_data;        /* 得到IP数据报的*/

    wait(ipfmutex);                /* 互斥*/

    if ((pip->ip_fragoff & (IP_FRAGOFF|IP_MF)) == 0) {    /*如果不是分片,返回当前帧*/
        signal(ipfmutex);
        return pep;
    }
    IpReasmReqds++;
    firstfree = -1;
    /* 以下情况为是分片 */
    for (i=0; i<IP_FQSIZE; ++i) {
        struct    ipfq    *piq = &ipfqt[i];

        if (piq->ipf_state == IPFF_FREE) {        /* 队列未使用,则继续*/
            if (firstfree == -1)
                firstfree = i;
            continue;
        }
        if (piq->ipf_id != pip->ip_id)            /* 队列ID不等于分片ID,则继续*/
            continue;
        if (piq->ipf_src != pip->ip_src)            /* 源地址不同,则继续*/
            continue;
        /* 找到匹配 */
        if (ipfadd(piq, pep) == 0) {            /* 把该分片加入匹配的队列*/
            signal(ipfmutex);
            return 0;
        }
        pep2 = ipfjoin(piq);                /* 检查是否可以重组数据报*/
        signal(ipfmutex);
        return pep2;
        
    }
    /* 没有匹配 */

    if (firstfree < 0) {                    /* 检查是否有空闲队列*/
        /* no room– drop */                /* 没有空闲则丢弃*/
        freebuf(pep);
        signal(ipfmutex);
        return 0;
    }
    ipfqt[firstfree].ipf_q = newq(IP_FQSIZE, QF_WAIT);    /* 分配一个空闲表项*/
    if (ipfqt[firstfree].ipf_q < 0) {
        freebuf(pep);
        signal(ipfmutex);
        return 0;
    }
    ipfqt[firstfree].ipf_src = pip->ip_src;            /* 填充*/
    ipfqt[firstfree].ipf_id = pip->ip_id;
    ipfqt[firstfree].ipf_ttl = IP_FTTL;
    ipfqt[firstfree].ipf_state = IPFF_VALID;
    ipfadd(&ipfqt[firstfree], pep);
    signal(ipfmutex);
    return 0;
}

int    ipfmutex;
struct    ipfq    ipfqt[IP_FQSIZE];

4.4 溢出时的丢弃

/* ipfadd.c – ipfadd */

#include <conf.h>
#include <kernel.h>
#include <proc.h>
#include <network.h>

/*————————————————————————
 *  ipfadd  -  增加一个分片到一个IP碎片队列
 *————————————————————————
 */
Bool
ipfadd(struct ipfq *iq, struct ep *pep)
{
    struct    ip    *pip;
    int        fragoff;

    if (iq->ipf_state != IPFF_VALID) {            /* 分片队列无效,则丢弃*/
        freebuf(pep);
        return FALSE;
    }
    pip = (struct ip *)pep->ep_data;                /* 得到IP数据报的*/
    fragoff = pip->ip_fragoff & IP_FRAGOFF;            /* 得到偏移量*/
    /* -fragoff用作关键值,越大越靠前 */
    if (enq(iq->ipf_q, pep, -fragoff) < 0) {            /* 举出丢弃并释放内存*/
        /* overflow– free all frags and drop */
        freebuf(pep);
        IpReasmFails++;
        while (pep = (struct ep *)deq(iq->ipf_q)) {    /* 从队列删除帧并释放帧*/
            freebuf(pep);
            IpReasmFails++;
        }
        freeq(iq->ipf_q);                /* 释放队列*/
        iq->ipf_state = IPFF_BOGUS;
        return FALSE;
    }
    iq->ipf_ttl = IP_FTTL;        /* 重置生存时间 */
    return TRUE;
}

4.5 测试一个完整的数据据报

/* ipfjoin.c – ipfjoin */

#include <conf.h>
#include <kernel.h>
#include <proc.h>
#include <network.h>

struct    ep    *ipfcons(struct ipfq *);

/*————————————————————————
 *  ipfjoin  -  join fragments, if all collected
 *————————————————————————
 */
struct ep *
ipfjoin(struct ipfq *iq)
{
    struct    ep    *pep;
    struct    ip     *pip = 0;
    int        off, packoff;

    if (iq->ipf_state == IPFF_BOGUS)
        return 0;
    /* see if we have the whole datagram */
    /* 看我们是否有整个的数据包 */

    off = 0;
    while (pep=(struct ep *)seeq(iq->ipf_q)) {        /* 取出帧*/
        pip = (struct ip *)pep->ep_data;            /* 取出IP报*/
        packoff =  (pip->ip_fragoff & IP_FRAGOFF)<<3;
        if (off < packoff) {                /* 偏移大于0*/
            while(seeq(iq->ipf_q))            /* 一个不满足,说没没全到*/
                /*empty*/;
            return 0;
        }
        off = packoff + pip->ip_len – IP_HLEN(pip);    /*计算总长度,不含头*/
    }
    /* 这里利用off来测试,首先ipfjoin查看当前数据报片的偏移量是否与off值相符。
       如果当前数据报片的偏移量超过了off的值,那么必定有尚未到达的数据报片,
       因此ipfjoin返回0。如果偏移量与off值一致,那么ipfjoin通过将off值加上当前
       数据报片长度减去首部计算出下一个数据报片的偏移量。*/
    if (off > MAXLRGBUF) {        /* 超过缓冲区则丢弃 – too big for us to handle */
        while (pep = (struct ep *)deq(iq->ipf_q))
            freebuf(pep);
        freeq(iq->ipf_q);
        iq->ipf_state = IPFF_FREE;
        return 0;
    }
    if (pip == 0 || (pip->ip_fragoff & IP_MF) == 0)        /* 没有IP报或没有更多的分片*/
        return ipfcons(iq);                /* 收集数据报片并重建完整的数据报 */

    return 0;
}

4.6 将数据报片组装成完整的数据报

/* ipfcons.c – ipfcons */

#include <conf.h>
#include <kernel.h>
#include <network.h>

/*————————————————————————
 *  ipfcons  -  从IP碎片队列构建一个分组
 *————————————————————————
 */
struct ep *
ipfcons(struct ipfq *iq)
{
    struct    ep    *pep, *peptmp;
    struct    ip    *pip;
    int        off, seq;

    pep = (struct ep *)getbuf(Net.lrgpool);            /* 申请缓存空间*/
    if (pep == (struct ep *)SYSERR) {            /* 申请失败则丢弃该报*/
        while (peptmp = (struct ep *)deq(iq->ipf_q)) {
            IpReasmFails++;
            freebuf(peptmp);
        }
        freeq(iq->ipf_q);                /* 释放队列*/
        iq->ipf_state = IPFF_FREE;
        return 0;
    }
    /*  复制帧和IP报头 */

    peptmp = (struct ep *)deq(iq->ipf_q);            /* 取出一个分片*/
    pip = (struct ip *)peptmp->ep_data;            /* 得到IP报*/
    off = IP_HLEN(pip);                    /* 得到IP头长度*/
    seq = 0;
    memcpy(pep, peptmp, EP_HLEN+off);            /* 复制IP报头到pep*/

    /* 复制数据部分 */
    while (peptmp != 0) {
        int dlen, doff;

        pip = (struct ip *)peptmp->ep_data;        /* 取IP报*/
        doff = IP_HLEN(pip) + seq
            - ((pip->ip_fragoff&IP_FRAGOFF)<<3);
        dlen = pip->ip_len – doff;
        memcpy(pep->ep_data+off, peptmp->ep_data+doff, dlen);
        off += dlen;
        seq += dlen;
        freebuf(peptmp);
        peptmp = (struct ep *)deq(iq->ipf_q);
    }

    /* 修复分组的头 */
    pip = (struct ip *)pep->ep_data;                /* 取出IP报*/
    pip->ip_len = off;                    /* 修复长度*/
    pip->ip_fragoff = 0;                    /* 修复偏移量*/

    /* 释放资源 */
    freeq(iq->ipf_q);
    iq->ipf_state = IPFF_FREE;
    IpReasmOKs++;
    return pep;
}

5. 数据报片链表的维护管理

/* ipftimer.c – ipftimer */

#include <conf.h>
#include <kernel.h>
#include <network.h>

/*————————————————————————
 * ipftimer – 更新生存周期并删除过期的碎片
 *————————————————————————
 */
void
ipftimer(int gran)
{
    struct    ep    *pep;
    struct    ip    *pip;
    int        i;

    wait(ipfmutex);                        /* 申请互斥量 */
    for (i=0; i<IP_FQSIZE; ++i) {                /* 遍历队列*/
        struct ipfq *iq = &ipfqt[i];

        if (iq->ipf_state == IPFF_FREE)            /* 空闲则继续*/
            continue;
        iq->ipf_ttl -= gran;                /* 非空闲则ttl-1*/
        if (iq->ipf_ttl <= 0) {                /* 生存周期到达则*/
            if (iq->ipf_state == IPFF_BOGUS) {    /* 如果为丢弃状态,则继续*/
                /* resources already gone */
                iq->ipf_state = IPFF_FREE;
                continue;
            }
            if (pep = (struct ep *)deq(iq->ipf_q)) {    /* 取分片*/
                IpReasmFails++;
                pip = (struct ip *)pep->ep_data;    /* 取IP报*/
                icmp(ICT_TIMEX, ICC_FTIMEX,    /* 向源站报错*/
                    pip->ip_src, pep, 0);
            }
            while (pep = (struct ep *)deq(iq->ipf_q)) {    /* 释放资源*/
                IpReasmFails++;
                freebuf(pep);
            }
            freeq(iq->ipf_q);            /* 释放队列*/
            iq->ipf_state = IPFF_FREE;
        }
    }
    signal(ipfmutex);                    /* 互斥解锁*/
}

6. 初始化

/* ipfinit.c – ipfinit */

#include <conf.h>
#include <kernel.h>
#include <network.h>

/*————————————————————————
 * ipfinit  -  initialize IP fragment queue data structures
 *————————————————————————
 */
void
ipfinit(void)
{
    int    i;

    ipfmutex = screate(1);            /* 不多说了,简单,太~~~,这个看不明白就不用看了. :) */
    for (i=0; i<IP_FQSIZE; ++i)
        ipfqt[i].ipf_state = IPFF_FREE;
}
 

]]>
http://www.kumouse.com/?feed=rss2&p=619 1