存档

2009年3月 的存档

IPv6与IPv4的UDP组播地址转换

2009年3月20日

这个东西可能对某些老师有用处,作者
交大饮水水源BBS ID:
rogerfd (Roger·璇) 共上站 1344 次 网龄792天 [巨蟹座]
上 次 在: [2009年03月20日08:59:33 星期五] 从 [211.144.112.64] 到本站一游。
目前在线:[讯息器:(打开) 呼叫器:(打开)] 生命力:[364] 文章:[297] 信箱:[ ]

转载自:
http://rogerfd.cn/?p=184

Roger的小程序系列(19)IPv6与IPv4的UDP组播地址转换

    工作中有时候需要把一路或者多路IPv6的UDP组播转换为IPv4的组播;有时候则相反,要把IPv4的转换为IPv6,于是写了一个小工具来统一完成这类的事情,Roger把它叫做IPv5,哈哈。

    IPv6的组播接收可以参考Roger之前的文章《Roger的小程序系列(2)IPv6组播工具》,发送也是比较简单的,每收到一个包就用sendto发出去就可以了。需要注意的事情是,这类的转发通常都是使用不同的网卡,一收一发,所以接收和发送都必须指明网络接口和IP地址。IPv6的接收和发送必须绑定IPv6的地址,IPv4的接受和发送则必须绑定IPv4的地址,不能混用。

    所以首先就是要遍历本机的所有网络接口和网络地址,这事情依赖API GetAdaptersAddresses,大致的代码是这样的

    ULONG uLen = 0;
    m_pInfo = NULL;
    //得到该结构的大小
    GetAdaptersAddresses (AF_UNSPEC, 0, 0, m_pInfo, &uLen);
    if (uLen <= 0)
    {
      return FALSE;
    }
    m_pInfo = (IP_ADAPTER_ADDRESSES*) malloc (uLen);
    if (!m_pInfo)
    {
      return FALSE;
    }
    if(ERROR_SUCCESS != GetAdaptersAddresses (AF_UNSPEC, 0, 0, m_pInfo, &uLen))
    {
      free(m_pInfo);
      return FALSE;
    }

    m_pInfo是 IP_ADAPTER_ADDRESSES 类型的指针,所有的网卡信息构成一个链表,下面这段代码来获取所有网卡的描述信息

    void CNewDlg::FillInf(CComboBox* pCombo)
    {
      IP_ADAPTER_ADDRESSES *q = NULL;
      pCombo->ResetContent ();
      for(q = m_pInfo; q ; q = q->Next)
      {
        CString str = q->Description;
        pCombo->AddString (str);
      }
      return;
    }

    以下的代码来遍历一个网络接口的所有地址,我们只关心单播的UnicastAddress

    void CNewDlg::FillAddr(int nIndex, CComboBox* pCombo)
    {
      IP_ADAPTER_ADDRESSES *q = NULL;
      int i = 0;
      pCombo->ResetContent ();
      char addr[256];
      for(q = m_pInfo; q; q = q->Next, ++i)
      {
        if (i == nIndex)
        {
          for (PIP_ADAPTER_UNICAST_ADDRESS pip = q->FirstUnicastAddress; pip ;
            pip = pip->Next) 
          {
            if(!getnameinfo(pip->Address.lpSockaddr,pip->Address.iSockaddrLength,
                  addr, sizeof addr,
                  0,0,NI_NUMERICHOST ))
            {
              pCombo->AddString (addr);
            }
          }
          break;
        }
      }
      return;
    }

    转换使用后台线程来干活,每个转换搞一个线程,转换的参数和状态信息放在一个全局变量里边。
    /* stdafx.h */

    enum ipv5_status
    {
      status_stop = 0,
      status_starting,
      status_running,
      status_error,
      status_stopping,
    };

    typedef struct _Convert_Info
    {
      char src_mc_addr [64];
      char src_mc_port [8];
      char src_inf_name[256];
      char src_inf_addr[64];
      char dst_mc_addr [64];
      char dst_mc_port [8];
      char dst_inf_name[256];
      char dst_inf_addr[64];
      bool cut_rtp_header;
      bool is_rtp;
      int  send_ttl;
      ipv5_status  status;
      SOCKET recv_socket;
      SOCKET send_socket;
      HANDLE hThread;
      double recvd_packets;
      double recvd_bytes;
      double err_packets;
      double packet_rate;
      double bit_rate;
      double err_rate;
    }Convert_Info;

    #define MAX_THREAD 16

    /* ipv5.cpp */
    Convert_Info g_arryInfo[MAX_THREAD];

    /* WorkTHread.cpp */

    #include “StdAfx.h”
    #include “ipv5.h”

    bool IsV6 (const char* addr)
    {
        return (strstr (addr, “::”) != NULL);
    }

    DWORD WINAPI ThreadProc (LPVOID Index)
    {
        ADDRINFO s1,*s2,s3,*s4;
        ADDRINFO s5,*s6,s7,*s8;
        WSABUF stWSABuf;                               
        SOCKADDR_IN6 addrFrom;
        DWORD dwIndex, dwTime1, dwTime2, nRet, dwParam, cbRet, iLen, iLost;
        USHORT index, oldindex = 0;
        char  buf[64*1024];
        double last_second_packets = 0, last_second_err_packets = 0, last_second_bytes = 0;
        dwIndex = (DWORD) Index;
        g_arryInfo[dwIndex].status = status_starting;
        bool bFirstPkt;

        int ttl = g_arryInfo[dwIndex].send_ttl;
        bool SrcV6 = IsV6 (g_arryInfo[dwIndex].src_inf_addr);
        bool DstV6 = IsV6 (g_arryInfo[dwIndex].dst_inf_addr);

        memset (&s1, 0, sizeof(s1));
        s1.ai_family   = SrcV6 ? AF_INET6 : AF_INET;
        s1.ai_socktype = SOCK_DGRAM;
        s1.ai_protocol = IPPROTO_UDP;
        s1.ai_flags    = AI_NUMERICHOST;
        nRet = getaddrinfo (g_arryInfo[dwIndex].src_mc_addr,
                            g_arryInfo[dwIndex].src_mc_port,
                            &s1,
                            &s2);
        if (nRet != 0)
        {
            goto end;
        }

        memset (&s3, 0, sizeof(s3));
        s3.ai_family   = SrcV6 ? AF_INET6 : AF_INET;
        s3.ai_socktype = SOCK_DGRAM;
        s3.ai_protocol = IPPROTO_UDP;
        s3.ai_flags    = AI_PASSIVE;
        nRet = getaddrinfo (g_arryInfo[dwIndex].src_inf_addr,
                            g_arryInfo[dwIndex].src_mc_port,
                            &s3,
                            &s4);
        if (nRet != 0)
        {
            goto end;
        }

        g_arryInfo[dwIndex].recv_socket =
            WSASocket ( SrcV6 ? AF_INET6 : AF_INET,
                        SOCK_DGRAM,
                        IPPROTO_UDP,
                        (LPWSAPROTOCOL_INFO)NULL,
                        0,
                        WSA_FLAG_OVERLAPPED |
                        WSA_FLAG_MULTIPOINT_C_LEAF |
                        WSA_FLAG_MULTIPOINT_D_LEAF);
        if (g_arryInfo[dwIndex].recv_socket == INVALID_SOCKET)
        {
            goto end;
        }

        dwParam = TRUE;
        nRet = setsockopt (
                            g_arryInfo[dwIndex].recv_socket,
                            SOL_SOCKET,
                            SO_REUSEADDR,
                            (char *)&dwParam,
                            sizeof (dwParam));
        if (nRet == SOCKET_ERROR)
        {
            goto end;
        }

        if (SOCKET_ERROR == bind (g_arryInfo[dwIndex].recv_socket,
                                    s4->ai_addr,
                                    s4->ai_addrlen))
        {
            goto end;  
        }

        dwParam = TRUE;
        nRet = WSAIoctl (g_arryInfo[dwIndex].recv_socket,
                        SIO_MULTIPOINT_LOOPBACK,
                        &dwParam,
                        sizeof (dwParam),
                        NULL,
                        0,
                        &cbRet,
                        NULL,
                        NULL);                                   
        if (nRet)
        {
            goto end;
        }

        g_arryInfo[dwIndex].recv_socket =
            WSAJoinLeaf (g_arryInfo[dwIndex].recv_socket, s2->ai_addr,
                        s2->ai_addrlen,
                        NULL,
                        NULL,
                        NULL,
                        NULL,
                        JL_RECEIVER_ONLY);             
        if (g_arryInfo[dwIndex].recv_socket == INVALID_SOCKET)
        {
            goto end;
        }
       
        dwParam = 2000;
        if(SOCKET_ERROR == setsockopt (g_arryInfo[dwIndex].recv_socket,
            SOL_SOCKET, SO_RCVTIMEO, (const char*)&dwParam,sizeof(dwParam)))
        {
            goto end;
        }

        dwParam = FALSE; //TRUE is Non-Blocking
        nRet = WSAIoctl (g_arryInfo[dwIndex].recv_socket,
                        FIONBIO,
                        &dwParam,
                        sizeof dwParam,
                        NULL,
                        0,
                        &cbRet,
                        0,
                        0);
        dwParam = 256*1024;
        nRet = setsockopt (g_arryInfo[dwIndex].recv_socket,
                            SOL_SOCKET,
                            SO_RCVBUF,
                            (char *)&dwParam,  
                            sizeof (dwParam));
        if (nRet == SOCKET_ERROR)
        {
            goto end;
        }

        memset (&s5, 0, sizeof(s5));
        s5.ai_family   = DstV6 ? AF_INET6 : AF_INET;
        s5.ai_socktype = SOCK_DGRAM;
        s5.ai_protocol = IPPROTO_UDP;
        s5.ai_flags    = AI_NUMERICHOST;
        nRet = getaddrinfo (g_arryInfo[dwIndex].dst_mc_addr,
                            g_arryInfo[dwIndex].dst_mc_port,
                            &s5,
                            &s6);
        if (nRet != 0)
        {
            goto end;
        }

        memset (&s7, 0, sizeof(s7));
        s7.ai_family   = DstV6 ? AF_INET6 : AF_INET;
        s7.ai_socktype = SOCK_DGRAM;
        s7.ai_protocol = IPPROTO_UDP;
        s7.ai_flags    = AI_PASSIVE;
        nRet = getaddrinfo (g_arryInfo[dwIndex].dst_inf_addr,
                            g_arryInfo[dwIndex].dst_mc_port,
                            &s7,
                            &s8);
        if (nRet != 0)
        {
            goto end;
        }

        g_arryInfo[dwIndex].send_socket = socket (DstV6 ? AF_INET6 : AF_INET,
                                                    SOCK_DGRAM,
                                                    IPPROTO_UDP);
        if (g_arryInfo[dwIndex].send_socket == INVALID_SOCKET)
        {
            goto end;
        }
           

        if (SOCKET_ERROR == setsockopt (g_arryInfo[dwIndex].send_socket,
                                        DstV6 ? IPPROTO_IPV6 : IPPROTO_IP,
                                        IP_MULTICAST_TTL,
                                        (const char*)&ttl,
                                        sizeof(int) ) )
        {
            int i = WSAGetLastError();
            goto end;
        }

        if (SOCKET_ERROR == bind (g_arryInfo[dwIndex].send_socket,
                                    s8->ai_addr,
                                    s8->ai_addrlen))
        {
            goto end;
        }

        dwTime1    = GetTickCount();
        bFirstPkt  = TRUE;
        iLost = 0;
        g_arryInfo[dwIndex].is_rtp = false;
        g_arryInfo[dwIndex].status = status_running;
        g_arryInfo[dwIndex].err_packets = g_arryInfo[dwIndex].recvd_packets = g_arryInfo[dwIndex].recvd_bytes = 0;
        g_arryInfo[dwIndex].bit_rate = g_arryInfo[dwIndex].err_rate = g_arryInfo[dwIndex].packet_rate = 0;
        while (g_arryInfo[dwIndex].status == status_running)
        {
            stWSABuf.buf = buf;
            stWSABuf.len = sizeof buf;
            cbRet        = 0;
            dwParam      = 0;
            iLen         = sizeof (addrFrom);
            nRet         = WSARecvFrom (g_arryInfo[dwIndex].recv_socket,
                                        &stWSABuf,
                                        1,
                                        &cbRet,
                                        &dwParam,
                                        (SOCKADDR*)&addrFrom,
                                        (int*)&iLen,
                                        NULL,
                                        NULL);
            if (nRet == SOCKET_ERROR )
            {
                if (WSAGetLastError() == WSAETIMEDOUT)
                {
                    continue;
                }
                else
                {
                    break;
                }
               
            }

            if (bFirstPkt)
            {
                if (cbRet >= 188*3 &&
                    stWSABuf.buf[0] == 0×47 &&
                    stWSABuf.buf[188] == 0×47 &&
                    stWSABuf.buf[188*2] == 0×47)
                {
                    g_arryInfo[dwIndex].is_rtp = false;
                }
                else
                {
                    g_arryInfo[dwIndex].is_rtp = true;
                }
            }

            g_arryInfo[dwIndex].recvd_packets += 1;
            if(g_arryInfo[dwIndex].is_rtp && cbRet < 12)
            {
                g_arryInfo[dwIndex].err_packets += 1;
                continue;
            }

            if (g_arryInfo[dwIndex].is_rtp)
            {
                //统计丢包
                index = ntohs (*((USHORT*)(stWSABuf.buf+2)));
                if (++oldindex != index)
                {
                    TRACE (”RTP Error! Excepet %d but got %d\n”, oldindex, index);
                    if (!bFirstPkt)
                    {
                        iLost = (index-oldindex) > 0 ? index-oldindex : oldindex-index;
                        g_arryInfo[dwIndex].err_packets += iLost;  
                    }
                    oldindex = index;
                }  
            }

            if (g_arryInfo[dwIndex].cut_rtp_header && g_arryInfo[dwIndex].is_rtp)
            {
                if (SOCKET_ERROR ==
                        sendto (g_arryInfo[dwIndex].send_socket,
                                buf + 12,
                                cbRet - 12,
                                0,
                                (const struct sockaddr FAR *)s6->ai_addr,
                                s6->ai_addrlen))
                {
                    goto end;
                }
            }
            else
            {
                if (SOCKET_ERROR ==
                        sendto (g_arryInfo[dwIndex].send_socket,
                                buf,
                                cbRet,
                                0,
                                (const struct sockaddr FAR *)s6->ai_addr,
                                s6->ai_addrlen))
                {
                    goto end;
                }
            }
            if(bFirstPkt)
            {
                bFirstPkt = FALSE;
            }

            g_arryInfo[dwIndex].recvd_bytes += cbRet;
            dwTime2 = GetTickCount();
            if(dwTime2 - dwTime1 >= 1000)
            {  
                dwTime1 = dwTime2;
                g_arryInfo[dwIndex].bit_rate = (g_arryInfo[dwIndex].recvd_bytes -
                    last_second_bytes) / 128;
                last_second_bytes = g_arryInfo[dwIndex].recvd_bytes;

                g_arryInfo[dwIndex].packet_rate = g_arryInfo[dwIndex].recvd_packets -
                    last_second_packets;
                last_second_packets = g_arryInfo[dwIndex].recvd_packets;

                if (g_arryInfo[dwIndex].packet_rate > 1)
                {
                    g_arryInfo[dwIndex].err_rate = 100.0* (g_arryInfo[dwIndex].err_packets -
                    last_second_err_packets) / g_arryInfo[dwIndex].packet_rate;
                }
                else
                {
                    g_arryInfo[dwIndex].err_rate = 0.0;
                }
                last_second_err_packets = g_arryInfo[dwIndex].err_packets;
               
            }

        }

    end:
        if (g_arryInfo[dwIndex].status != status_stopping)
        {
            // error exit
            g_arryInfo[dwIndex].status = status_error;
        }
        else
        {
            g_arryInfo[dwIndex].status = status_stop;
        }
        g_arryInfo[dwIndex].err_packets = g_arryInfo[dwIndex].recvd_packets = g_arryInfo[dwIndex].recvd_bytes = 0;
        g_arryInfo[dwIndex].bit_rate = g_arryInfo[dwIndex].err_rate = g_arryInfo[dwIndex].packet_rate = 0;
        closesocket (g_arryInfo[dwIndex].recv_socket);
        closesocket (g_arryInfo[dwIndex].send_socket);
        return 0;
    }

    运行的样子

    完整代码就不给出来了,这里有可执行程序的下载:  ipv5

————————————————————————
作者: roger
Blog: http://rogerfd.cn
Email:roger99707@163.com
本文欢迎转载和引用,请保留本说明并注明出处
————————————————————————

kaida Work

Joke一则:取经

2009年3月17日

唐僧师徒历经九九八十一难,终于见到了如来佛求取真经.

如来问:“你们带U盘了么?”

唐僧师徒: no

如来又问:“移动硬盘呢?”

唐僧师徒: no

如来继续问:“ IPOD也可以哇”

唐僧师徒: no

如来叹了口气:“那你们就原路回去吧,我用QQ传给你们

唐僧: ,早知道加你QQ就完了,老子还走这么远干嘛啊.

如来的回应道:“你们以为要加就加啊,我经常隐身滴! 最后,如来还来句:你们有没
psp啊?

唐僧:…….

如来: 那这么远的路,你们是怎么娱乐的?

唐僧师徒:打怪升级

后续:

唐僧回去加了如来QQ

传数据中..

如来:怎么这么慢呢,你什么网啊?

唐僧:校园网。。。

如来: 。。。你再来一趟吧

kaida 未分类

[转载]Autorun.inf时代快结束了吧

2009年3月9日

我一个学生写的。

发信人: eaufavor (无雨飘·红伞控·半人马α大使), 信区: virus
标  题: Autorun.inf时代快结束了吧
发信站: 饮水思源 (2009年03月09日13:47:24 星期一)

    今天在自己的机器上玩autorun.inf,发现怎么都不能让系统加载这个文件,MountPo
int2键值下只加载autorun中定义图标的部分。一google才记起来是微软搞的鬼。微软去年
八月份发布了KB950582补丁,针对自动播放。
    其中:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\Explorer

“NoDriveTypeAutoRun”=dword:000000ff”  键值可以禁止MountPoint2加载autorun中的信

“HonorAutoRunSetting”=dword:00000001″ 键值可以使MountPoint2中的键值不反映到双击
和右键菜单中。

在两个键值都存在的情况下,MountPoint2无视autorun.inf中除icon部分以外的信息。
删除NoDriveTypeAutoRun,MountPoint2加载autorun.inf,可以看到shell等部分,但双击
、右键菜单没反应。
再删除HonorAutoRunSetting,左键双击,右键菜单均符合autorun.inf中写的内容。

详见http://support.microsoft.com/kb/953252/zh-cn

这个故事告诉我们,要勤于打Windows补丁。


                      谁说行为不是美?
新年愿望
1好好做编译作业(独立完成)2多发有实质意义的讨论(努力中)3不要乱搭讪(做不到)

拜茄教教主 && 交大红伞控第一人 && 希区柯克夫人
http://bbs.sjtu.edu.cn/file/test/1220270993205440.gif
我的个人主页:http://bbs.sjtu.edu.cn/file/virus/1235827431261450.html

※ 来源:·饮水思源 bbs.sjtu.edu.cn·[FROM: 59.78.45.122]

kaida Work

IPv6网站目录

2009年3月5日

http://sixy.ch

这种IPv6网站目录在当前还是有市场的。

又想起了多年前的 Yahoo 人工分类目录了。

其实这种类型网站我们也可以架一个类似的,不过现在没那么多精力折腾了。

kaida Tips

MAC地址和厂商的对应关系

2009年3月4日

因为需要了解MAC地址和厂商的对应关系,故找了一下

http://standards.ieee.org/regauth/oui/index.shtml

这里有提供 IEEE OUI and Company_id Assignments 的查询和库下载.

可能对某些特定需求有用处.

kaida Work