source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/BridgeUnix.c @ a1bae3e

trunk
Last change on this file since a1bae3e was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

  • Property mode set to 100644
File size: 37.8 KB
Line 
1// SoftEther UT-VPN SourceCode
2//
3// Copyright (C) 2004-2010 SoftEther Corporation.
4// Copyright (C) 2004-2010 University of Tsukuba, Japan.
5// Copyright (C) 2003-2010 Daiyuu Nobori.
6// All Rights Reserved.
7//
8// http://utvpn.tsukuba.ac.jp/
9//
10// This program is free software; you can redistribute it and/or
11// modify it under the terms of the GNU General Public License
12// version 2 as published by the Free Software Foundation.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License version 2
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22//
23// このファイルは GPL バージョン 2 ライセンスで公開されています。
24// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
25// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
26// を除去することはできません。改変した著作物を配布する場合は、改変実施者の
27// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
28//
29// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
30// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
31// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
32// ホストされています。
33// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
34// および、試験または研究のために利用が行われることを想定して配布
35// しています。
36// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
37// あります。
38// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
39// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
40// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
41// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
42// に組み込みさせていただきます。
43//
44// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
45// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
46//
47// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
48// (SoftEther Corporation) およびその他の著作権保持者が保有しています。
49// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
50// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
51// ください。
52//
53// お願い: どのような通信ソフトウェアにも通常は必ず未発見の
54// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
55// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
56// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
57// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
58// 公益保護にご協力いただきますようお願い申し上げます。
59//
60// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
61// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
62// を保護するための努力を行います。
63//
64// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
65// 日本国内の脆弱性情報届出受付公的機関:
66//         独立行政法人 情報処理推進機構
67//         http://www.ipa.go.jp/security/vuln/report/
68//
69// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
70// 連絡先: http://www.softether.co.jp/jp/contact/
71
72// -----------------------------------------------
73// [ChangeLog]
74// 2010.05.20
75//  新規リリース by SoftEther
76// -----------------------------------------------
77
78// BridgeUnix.c
79// Ethernet ブリッジプログラム (UNIX 版)
80//#define   BRIDGE_C
81//#define   UNIX_LINUX
82
83#ifdef  BRIDGE_C
84
85#include <stdio.h>
86#include <stdlib.h>
87#include <string.h>
88#include <wchar.h>
89#include <stdarg.h>
90#include <time.h>
91#include <errno.h>
92#include <Mayaqua/Mayaqua.h>
93#include <Cedar/Cedar.h>
94
95#ifdef UNIX_SOLARIS
96#include <sys/sockio.h>
97#endif
98
99#ifdef BRIDGE_PCAP
100#include <pcap.h>
101#endif // BRIDGE_PCAP
102
103#ifdef BRIDGE_BPF
104#include <sys/ioctl.h>
105#include <net/bpf.h>
106#include <net/if_types.h>
107#include <net/if_dl.h>
108#include <ifaddrs.h>
109#endif // BRIDGE_BPF
110
111// 初期化
112void InitEth()
113{
114}
115
116// 解放
117void FreeEth()
118{
119}
120
121// Unix のデバイスの説明文字列の取得がサポートされているかどうか取得
122bool EthIsInterfaceDescriptionSupportedUnix()
123{
124    bool ret = false;
125    DIRLIST *d = EnumDir("/etc/sysconfig/networking/devices/");
126
127    if (d == NULL)
128    {
129        return false;
130    }
131
132    if (d->NumFiles >= 1)
133    {
134        ret = true;
135    }
136
137    FreeDir(d);
138
139    return ret;
140}
141
142// Unix のデバイスの説明文字列を取得
143bool EthGetInterfaceDescriptionUnix(char *name, char *str, UINT size)
144{
145    char tmp[MAX_SIZE];
146    bool ret = false;
147    BUF *b;
148    // 引数チェック
149    if (name == NULL || str == NULL)
150    {
151        return false;
152    }
153
154    StrCpy(str, size, name);
155
156    Format(tmp, sizeof(tmp), "/etc/sysconfig/networking/devices/ifcfg-%s", name);
157
158    b = ReadDump(tmp);
159    if (b != NULL)
160    {
161        char *line = CfgReadNextLine(b);
162
163        if (IsEmptyStr(line) == false)
164        {
165            if (StartWith(line, "#"))
166            {
167                char tmp[MAX_SIZE];
168
169                StrCpy(tmp, sizeof(tmp), line + 1);
170
171                Trim(tmp);
172                tmp[60] = 0;
173
174                StrCpy(str, size, tmp);
175
176                ret = true;
177            }
178        }
179
180        Free(line);
181
182        FreeBuf(b);
183    }
184
185    return ret;
186}
187
188// Raw ソケットを開く
189int UnixEthOpenRawSocket()
190{
191#ifdef  UNIX_LINUX
192    int s;
193
194    s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
195    if (s < 0)
196    {
197        return INVALID_SOCKET;
198    }
199    else
200    {
201        return s;
202    }
203#else   // UNIX_LINUX
204    return -1;
205#endif  // UNIX_LINUX
206}
207
208// Ethernet 操作がサポートされているかどうか
209bool IsEthSupported()
210{
211    bool ret = false;
212
213#if     defined(UNIX_LINUX)
214    ret = IsEthSupportedLinux();
215#elif   defined(UNIX_SOLARIS)
216    ret = IsEthSupportedSolaris();
217#elif   defined(BRIDGE_PCAP)
218    ret = true;
219#elif   defined(BRIDGE_BPF)
220    ret = true;
221#endif
222    return ret;
223}
224
225#ifdef  UNIX_LINUX
226bool IsEthSupportedLinux()
227{
228    int s;
229
230    // Raw ソケットを開いてみる
231    s = UnixEthOpenRawSocket();
232    if (s == INVALID_SOCKET)
233    {
234        // 失敗
235        return false;
236    }
237
238    // 成功
239    closesocket(s);
240
241    return true;
242}
243#endif  // UNIX_LINUX
244
245#ifdef  UNIX_SOLARIS
246bool IsEthSupportedSolaris()
247{
248    return true;
249}
250#endif  // UNIX_SOLARIS
251
252#ifdef  UNIX_SOLARIS
253// アダプタ一覧を取得 (Solaris)
254TOKEN_LIST *GetEthListSolaris()
255{
256    TOKEN_LIST *t;
257    int i, s;
258    LIST *o;
259
260
261    o = NewListFast(CompareStr);
262    s = socket(AF_INET, SOCK_DGRAM, 0);
263    if (s != INVALID_SOCKET)
264    {
265        struct lifnum lifn;
266        lifn.lifn_family = AF_INET;
267        lifn.lifn_flags = 0;
268        if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) >= 0)
269        {
270            struct lifconf lifc;
271            struct lifreq *buf;
272            UINT numifs;
273            UINT bufsize;
274           
275            numifs = lifn.lifn_count;
276            Debug("NumIFs:%d\n",numifs);
277            bufsize = numifs * sizeof(struct lifreq);
278            buf = Malloc(bufsize);
279
280            lifc.lifc_family = AF_INET;
281            lifc.lifc_flags = 0;
282            lifc.lifc_len = bufsize;
283            lifc.lifc_buf = (char*) buf;
284            if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) >= 0)
285            {
286                for (i = 0; i<numifs; i++)
287                {
288                    if(StartWith(buf[i].lifr_name, "lo") == false){
289                        Add(o, CopyStr(buf[i].lifr_name));
290                    }
291                }
292            }
293            Free(buf);
294        }
295        closesocket(s);
296    }
297
298    Sort(o);
299
300    t = ZeroMalloc(sizeof(TOKEN_LIST));
301    t->NumTokens = LIST_NUM(o);
302    t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
303
304    for (i = 0;i < LIST_NUM(o);i++)
305    {
306        char *name = LIST_DATA(o, i);
307        t->Token[i] = name;
308    }
309
310    ReleaseList(o);
311
312    return t;
313}
314#endif  // UNIX_SOLARIS
315
316#ifdef  UNIX_LINUX
317// アダプタ一覧を取得 (Linux)
318TOKEN_LIST *GetEthListLinux()
319{
320    struct ifreq ifr;
321    TOKEN_LIST *t;
322    UINT i, n;
323    int s;
324    LIST *o;
325    char name[MAX_SIZE];
326
327    o = NewListFast(CompareStr);
328
329    s = UnixEthOpenRawSocket();
330    if (s != INVALID_SOCKET)
331    {
332        n = 0;
333        for (i = 0;;i++)
334        {
335            Zero(&ifr, sizeof(ifr));
336            ifr.ifr_ifindex = i;
337
338            if (ioctl(s, SIOCGIFNAME, &ifr) >= 0)
339            {
340                n = 0;
341                StrCpy(name, sizeof(name), ifr.ifr_name);
342
343                Zero(&ifr, sizeof(ifr));
344                StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
345                if (ioctl(s, SIOCGIFHWADDR, &ifr) >= 0)
346                {
347                    UINT type = ifr.ifr_hwaddr.sa_family;
348                    if (type == 1 || type == 2 || type == 6 || type == 800 || type == 801)
349                    {
350                        if (IsInListStr(o, name) == false)
351                        {
352                            if (StartWith(name, "tap_") == false)
353                            {
354                                Add(o, CopyStr(name));
355                            }
356                        }
357                    }
358                }
359            }
360            else
361            {
362                n++;
363                if (n >= 64)
364                {
365                    break;
366                }
367            }
368        }
369        closesocket(s);
370    }
371
372    Sort(o);
373
374    t = ZeroMalloc(sizeof(TOKEN_LIST));
375    t->NumTokens = LIST_NUM(o);
376    t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
377
378    for (i = 0;i < LIST_NUM(o);i++)
379    {
380        char *name = LIST_DATA(o, i);
381        t->Token[i] = name;
382    }
383
384    ReleaseList(o);
385
386    return t;
387}
388#endif  // UNIX_LINUX
389
390#ifdef BRIDGE_PCAP
391// アダプタ一覧を取得 (Pcap)
392TOKEN_LIST *GetEthListPcap()
393{
394    pcap_if_t *alldevs;
395    char errbuf[PCAP_ERRBUF_SIZE];
396    LIST *o;
397    TOKEN_LIST *t;
398    int i;
399
400    o = NewListFast(CompareStr);
401
402    if( pcap_findalldevs(&alldevs,errbuf) != -1)
403    {
404        pcap_if_t *dev = alldevs;
405        while(dev != NULL)
406        {
407            pcap_t *p;
408            // デバイスを開いてみないとデバイスの種類が分からない?
409            p = pcap_open_live(dev->name, 0, false, 0, errbuf);
410            if(p != NULL)
411            {
412                int datalink = pcap_datalink(p);
413    //          Debug("type:%s\n",pcap_datalink_val_to_name(datalink));
414                pcap_close(p);
415                if(datalink == DLT_EN10MB){
416                    // イーサネットデバイスのみ列挙する
417                    Add(o, CopyStr(dev->name));
418                }
419            }
420            dev = dev->next;
421        }
422        pcap_freealldevs(alldevs);
423    }
424   
425    Sort(o);
426    t = ZeroMalloc(sizeof(TOKEN_LIST));
427    t->NumTokens = LIST_NUM(o);
428    t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
429    for (i = 0;i < LIST_NUM(o);i++)
430    {
431        t->Token[i] = LIST_DATA(o, i);
432    }
433    ReleaseList(o);
434    return t;
435}
436#endif // BRIDGE_PCAP
437
438#ifdef BRIDGE_BPF
439// アダプタ一覧を取得 (BPF)
440TOKEN_LIST *GetEthListBpf()
441{
442    struct ifaddrs *ifadrs;
443    struct sockaddr_dl *sockadr;
444    LIST *o;
445    TOKEN_LIST *t;
446    int i;
447
448    o = NewListFast(CompareStr);
449
450    // ネットワークデバイスの一覧を取得
451    if(getifaddrs( &ifadrs ) == 0)
452    {
453        struct ifaddrs *ifadr = ifadrs;
454        while(ifadr)
455        {
456            sockadr = (struct sockaddr_dl*)ifadr->ifa_addr;
457            if(sockadr->sdl_family == AF_LINK && sockadr->sdl_type == IFT_ETHER)
458            {
459                // Ethernet デバイスか?
460                if(!IsInListStr(o,ifadr->ifa_name))
461                {
462                    // 既存でなければ追加(複数のMACアドレスを持つインターフェースへの対策)
463                    Add(o, CopyStr(ifadr->ifa_name));
464                }
465            }
466            ifadr = ifadr -> ifa_next;
467        }
468        freeifaddrs(ifadrs);
469    }
470
471    Sort(o);
472    t = ZeroMalloc(sizeof(TOKEN_LIST));
473    t->NumTokens = LIST_NUM(o);
474    t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
475    for (i = 0;i < LIST_NUM(o);i++)
476    {
477        t->Token[i] = LIST_DATA(o, i);
478    }
479    ReleaseList(o);
480    return t;
481}
482#endif // BRIDGE_BPF
483
484// アダプタ一覧を取得
485TOKEN_LIST *GetEthList()
486{
487    TOKEN_LIST *t = NULL;
488
489#if defined(UNIX_LINUX)
490    t = GetEthListLinux();
491#elif   defined(UNIX_SOLARIS)
492    t = GetEthListSolaris();
493#elif   defined(BRIDGE_PCAP)
494    t = GetEthListPcap();
495#elif   defined(BRIDGE_BPF)
496    t = GetEthListBpf();
497#endif
498
499    return t;
500}
501
502#ifdef  UNIX_LINUX
503// アダプタを開く (Linux)
504ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
505{
506    ETH *e;
507    struct ifreq ifr;
508    struct sockaddr_ll addr;
509    int s;
510    int index;
511    CANCEL *c;
512    // 引数チェック
513    if (name == NULL)
514    {
515        return NULL;
516    }
517
518    if (tapmode)
519    {
520#ifndef NO_VLAN
521        // tap モードの場合
522        VLAN *v = NewTap(name, tapaddr);
523        if (v == NULL)
524        {
525            return NULL;
526        }
527
528        e = ZeroMalloc(sizeof(ETH));
529        e->Name = CopyStr(name);
530        e->Title = CopyStr(name);
531        e->Cancel = VLanGetCancel(v);
532        e->IfIndex = 0;
533        e->Socket = INVALID_SOCKET;
534        e->Tap = v;
535
536        return e;
537#else   // NO_VLAN
538        return NULL;
539#endif  // NO_VLAN
540    }
541
542    s = UnixEthOpenRawSocket();
543    if (s == INVALID_SOCKET)
544    {
545        return NULL;
546    }
547
548    Zero(&ifr, sizeof(ifr));
549    StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
550
551    if (ioctl(s, SIOCGIFINDEX, &ifr) < 0)
552    {
553        closesocket(s);
554        return NULL;
555    }
556
557    index = ifr.ifr_ifindex;
558
559    Zero(&addr, sizeof(addr));
560    addr.sll_family = PF_PACKET;
561    addr.sll_protocol = htons(ETH_P_ALL);
562    addr.sll_ifindex = index;
563
564    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
565    {
566        closesocket(s);
567        return NULL;
568    }
569
570    if (local == false)
571    {
572        // プロミスキャスモードに設定する
573        Zero(&ifr, sizeof(ifr));
574        StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
575        if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
576        {
577            // 失敗
578            closesocket(s);
579            return NULL;
580        }
581
582        ifr.ifr_flags |= IFF_PROMISC;
583
584        if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
585        {
586            // 失敗
587            closesocket(s);
588            return NULL;
589        }
590    }
591
592    e = ZeroMalloc(sizeof(ETH));
593    e->Name = CopyStr(name);
594    e->Title = CopyStr(name);
595    e->IfIndex = index;
596    e->Socket = s;
597
598    c = NewCancel();
599    UnixDeletePipe(c->pipe_read, c->pipe_write);
600    c->pipe_read = c->pipe_write = -1;
601
602    UnixSetSocketNonBlockingMode(s, true);
603
604    c->SpecialFlag = true;
605    c->pipe_read = s;
606
607    e->Cancel = c;
608
609    // MTU の取得
610    e->InitialMtu = EthGetMtu(e);
611
612    return e;
613}
614#endif  // UNIX_LINUX
615
616// MTU の値を取得
617UINT EthGetMtu(ETH *e)
618{
619#if defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
620    UINT ret = 0;
621#ifdef  UNIX_SOLARIS
622    struct lifreq ifr;
623#else   // UNIX_SOLARIS
624    struct ifreq ifr;
625#endif  // UNIX_SOLARIS
626    int s;
627    // 引数チェック
628    if (e == NULL || e->Tap != NULL)
629    {
630        return 0;
631    }
632
633    if (e->CurrentMtu != 0)
634    {
635        return e->CurrentMtu;
636    }
637
638#if defined(UNIX_BSD) || defined(UNIX_SOLARIS)
639    s = e->SocketBsdIf;
640#else   // defined(UNIX_BSD) || defined(UNIX_SOLARIS)
641    s = e->Socket;
642#endif  // defined(UNIX_BSD) || defined(UNIX_SOLARIS)
643
644    Zero(&ifr, sizeof(ifr));
645
646#ifdef  UNIX_SOLARIS
647    StrCpy(ifr.lifr_name, sizeof(ifr.lifr_name), e->Name);
648#else   // UNIX_SOLARIS
649    StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), e->Name);
650#endif  // UNIX_SOLARIS
651
652#ifdef  UNIX_SOLARIS
653    if (ioctl(s, SIOCGLIFMTU, &ifr) < 0)
654    {
655        // 失敗
656        return 0;
657    }
658#else   // UNIX_SOLARIS
659    if (ioctl(s, SIOCGIFMTU, &ifr) < 0)
660    {
661        // 失敗
662        return 0;
663    }
664#endif  // UNIX_SOLARIS
665
666#ifdef  UNIX_SOLARIS
667    ret = ifr.lifr_mtu + 14;
668#else   // UNIX_SOLARIS
669    ret = ifr.ifr_mtu + 14;
670#endif  // UNIX_SOLARIS
671
672    e->CurrentMtu = ret;
673
674    Debug("%s: GetMtu: %u\n", e->Name, ret);
675
676    return ret;
677#else   // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
678    return 0;
679#endif  // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
680}
681
682// MTU の値を設定
683bool EthSetMtu(ETH *e, UINT mtu)
684{
685#if defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
686    UINT ret = 0;
687#ifdef  UNIX_SOLARIS
688    struct lifreq ifr;
689#else   // UNIX_SOLARIS
690    struct ifreq ifr;
691#endif  // UNIX_SOLARIS
692    int s;
693    // 引数チェック
694    if (e == NULL || e->Tap != NULL || (mtu > 1 && mtu < 1514))
695    {
696        return false;
697    }
698    if (mtu == 0 && e->InitialMtu == 0)
699    {
700        return false;
701    }
702
703    if (mtu == 0)
704    {
705        // mtu == 0 の場合は MTU の値を元に戻す
706        mtu = e->InitialMtu;
707    }
708
709#if defined(UNIX_BSD) || defined(UNIX_SOLARIS)
710    s = e->SocketBsdIf;
711#else   // defined(UNIX_BSD) || defined(UNIX_SOLARIS)
712    s = e->Socket;
713#endif  // defined(UNIX_BSD) || defined(UNIX_SOLARIS)
714
715    if (e->CurrentMtu == mtu)
716    {
717        // 変更の必要なし
718        return true;
719    }
720
721    Zero(&ifr, sizeof(ifr));
722
723#ifdef  UNIX_SOLARIS
724    StrCpy(ifr.lifr_name, sizeof(ifr.lifr_name), e->Name);
725    ifr.lifr_mtu = mtu - 14;
726#else   // UNIX_SOLARIS
727    StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), e->Name);
728    ifr.ifr_mtu = mtu - 14;
729#endif  // UNIX_SOLARIS
730
731#ifdef  UNIX_SOLARIS
732    if (ioctl(s, SIOCSLIFMTU, &ifr) < 0)
733    {
734        // 失敗
735        return false;
736    }
737#else   // UNIX_SOLARIS
738    if (ioctl(s, SIOCSIFMTU, &ifr) < 0)
739    {
740        // 失敗
741        return false;
742    }
743#endif  // UNIX_SOLARIS
744
745    e->CurrentMtu = mtu;
746
747    Debug("%s: SetMtu: %u\n", e->Name, mtu);
748
749    return true;
750#else   // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
751    return false;
752#endif  // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
753}
754
755// MTU の値の変更がサポートされているかどうか取得
756bool EthIsChangeMtuSupported(ETH *e)
757{
758#if defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
759    // 引数チェック
760    if (e == NULL || e->Tap != NULL)
761    {
762        return false;
763    }
764
765    return true;
766#else   // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
767    return false;
768#endif  // defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
769}
770
771#ifdef  UNIX_SOLARIS
772// アダプタを開く (Solaris)
773ETH *OpenEthSolaris(char *name, bool local, bool tapmode, char *tapaddr)
774{
775    char devname[MAX_SIZE];
776    UINT devid;
777    int fd;
778    ETH *e;
779    CANCEL *c;
780    struct strioctl sioc;
781
782    // 引数チェック
783    if (name == NULL || tapmode != false)
784    {
785        return NULL;
786    }
787
788    // デバイス名を解析
789    if (ParseUnixEthDeviceName(devname, sizeof(devname), &devid, name) == false)
790    {
791        return NULL;
792    }
793
794    // デバイスを開く
795    fd = open(devname, O_RDWR);
796    if (fd == -1)
797    {
798        // 失敗
799        return NULL;
800    }
801
802    // デバイスにアタッチする
803    if (DlipAttatchRequest(fd, devid) == false)
804    {
805        // 失敗
806        close(fd);
807        return NULL;
808    }
809
810    // 確認
811    if (DlipReceiveAck(fd) == false)
812    {
813        // 失敗
814        close(fd);
815        return NULL;
816    }
817
818    // SAPにバインドする
819    if (DlipBindRequest(fd) == false)
820    {
821        // 失敗
822        close(fd);
823        return NULL;
824    }
825
826    // 確認
827    if (DlipReceiveAck(fd) == false)
828    {
829        // 失敗
830        close(fd);
831        return NULL;
832    }
833
834    // SAPに関わらず受信するモードにセットする
835    if (DlipPromiscuous(fd, DL_PROMISC_SAP) == false)
836    {
837        // 失敗
838        close(fd);
839        return NULL;
840    }
841
842    // 確認
843    if (DlipReceiveAck(fd) == false)
844    {
845        // 失敗
846        close(fd);
847        return NULL;
848    }
849
850    // 自分の送信するパケットも受信するモードにセットする
851    if (DlipPromiscuous(fd, DL_PROMISC_PHYS) == false)
852    {
853        // 失敗
854        close(fd);
855        return NULL;
856    }
857
858    // 確認
859    if (DlipReceiveAck(fd) == false)
860    {
861        // 失敗
862        close(fd);
863        return NULL;
864    }
865
866    // Raw モードに設定
867    sioc.ic_cmd = DLIOCRAW;
868    sioc.ic_timout = -1;
869    sioc.ic_len = 0;
870    sioc.ic_dp = NULL;
871    if (ioctl(fd, I_STR, &sioc) < 0)
872    {
873        // 失敗
874        close(fd);
875        return NULL;
876    }
877
878    if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
879    {
880        // 失敗
881        close(fd);
882        return NULL;
883    }
884
885    e = ZeroMalloc(sizeof(ETH));
886    e->Name = CopyStr(name);
887    e->Title = CopyStr(name);
888
889    c = NewCancel();
890    UnixDeletePipe(c->pipe_read, c->pipe_write);
891    c->pipe_read = c->pipe_write = -1;
892
893    c->SpecialFlag = true;
894    c->pipe_read = fd;
895
896    e->Cancel = c;
897
898    e->IfIndex = -1;
899    e->Socket = fd;
900
901    UnixSetSocketNonBlockingMode(fd, true);
902
903    // 操作用 I/F の取得
904    e->SocketBsdIf = socket(AF_INET, SOCK_DGRAM, 0);
905
906    // MTU の取得
907    e->InitialMtu = EthGetMtu(e);
908
909    return e;
910}
911
912// プロミスキャスモードにセットする
913bool DlipPromiscuous(int fd, UINT level)
914{
915    dl_promiscon_req_t req;
916    struct strbuf ctl;
917    int flags;
918    // 引数チェック
919    if (fd == -1)
920    {
921        return false;
922    }
923
924    Zero(&req, sizeof(req));
925    req.dl_primitive = DL_PROMISCON_REQ;
926    req.dl_level = level;
927
928    Zero(&ctl, sizeof(ctl));
929    ctl.maxlen = 0;
930    ctl.len = sizeof(req);
931    ctl.buf = (char *)&req;
932
933    flags = 0;
934
935    if (putmsg(fd, &ctl, NULL, flags) < 0)
936    {
937        return false;
938    }
939
940    return true;
941}
942
943// SAPにバインドする
944bool DlipBindRequest(int fd)
945{
946    dl_bind_req_t   req;
947    struct strbuf ctl;
948
949    if (fd == -1)
950    {
951        return false;
952    }
953
954    Zero(&req, sizeof(req));
955    req.dl_primitive = DL_BIND_REQ;
956    req.dl_service_mode = DL_CLDLS;
957    req.dl_sap = 0;
958
959    Zero(&ctl, sizeof(ctl));
960    ctl.maxlen = 0;
961    ctl.len = sizeof(req);
962    ctl.buf = (char *)&req;
963
964    if (putmsg(fd, &ctl, NULL, 0) < 0)
965    {
966        return false;
967    }
968    return true;
969}
970
971// デバイスにアタッチする
972bool DlipAttatchRequest(int fd, UINT devid)
973{
974    dl_attach_req_t req;
975    struct strbuf ctl;
976    int flags;
977    // 引数チェック
978    if (fd == -1)
979    {
980        return false;
981    }
982
983    Zero(&req, sizeof(req));
984    req.dl_primitive = DL_ATTACH_REQ;
985    req.dl_ppa = devid;
986
987    Zero(&ctl, sizeof(ctl));
988    ctl.maxlen = 0;
989    ctl.len = sizeof(req);
990    ctl.buf = (char *)&req;
991
992    flags = 0;
993
994    if (putmsg(fd, &ctl, NULL, flags) < 0)
995    {
996        return false;
997    }
998
999    return true;
1000}
1001
1002// 確認応答を受信する
1003bool DlipReceiveAck(int fd)
1004{
1005    union DL_primitives *dlp;
1006    struct strbuf ctl;
1007    int flags = 0;
1008    char *buf;
1009    // 引数チェック
1010    if (fd == -1)
1011    {
1012        return false;
1013    }
1014
1015    buf = MallocFast(SOLARIS_MAXDLBUF);
1016
1017    Zero(&ctl, sizeof(ctl));
1018    ctl.maxlen = SOLARIS_MAXDLBUF;
1019    ctl.len = 0;
1020    ctl.buf = buf;
1021
1022    if (getmsg(fd, &ctl, NULL, &flags) < 0)
1023    {
1024        return false;
1025    }
1026
1027    dlp = (union DL_primitives *)ctl.buf;
1028    if (dlp->dl_primitive != (UINT)DL_OK_ACK && dlp->dl_primitive != (UINT)DL_BIND_ACK)
1029    {
1030        Free(buf);
1031        return false;
1032    }
1033
1034    Free(buf);
1035
1036    return true;
1037}
1038
1039#endif  // UNIX_SOLARIS
1040
1041// UNIX のデバイス名文字列をデバイス名と番号に分ける
1042bool ParseUnixEthDeviceName(char *dst_devname, UINT dst_devname_size, UINT *dst_devid, char *src_name)
1043{
1044    UINT len, i, j;
1045
1046    // 引数チェック
1047    if (dst_devname == NULL || dst_devid == NULL || src_name == NULL)
1048    {
1049        return false;
1050    }
1051
1052    len = strlen(src_name);
1053    // 文字列長チェック
1054    if(len == 0)
1055    {
1056        return false;
1057    }
1058
1059    for (i = len-1; i+1 != 0; i--)
1060    {
1061        // 末尾からたどって最初に数字でない文字を検出
1062        if (src_name[i] < '0' || '9' < src_name[i])
1063        {
1064            // 最後の文字が数字でなければエラー
1065            if(src_name[i+1]==0)
1066            {
1067                return false;
1068            }
1069            *dst_devid = ToInt(src_name + i + 1);
1070            StrCpy(dst_devname, dst_devname_size, "/dev/");
1071            for (j = 0; j<i+1 && j<dst_devname_size-6; j++)
1072            {
1073                dst_devname[j+5] = src_name[j];
1074            }
1075            dst_devname[j+5]=0;
1076            return true;
1077        }
1078    }
1079    // 全て数字ならエラー
1080    return false;
1081}
1082
1083#if defined(BRIDGE_BPF) || defined(BRIDGE_PCAP)
1084// キャプチャしたパケットデータ構造体の初期化
1085struct CAPTUREBLOCK *NewCaptureBlock(UCHAR *data, UINT size){
1086    struct CAPTUREBLOCK *block = Malloc(sizeof(struct CAPTUREBLOCK));
1087    block->Buf = data;
1088    block->Size = size;
1089    return block;
1090}
1091
1092// キャプチャしたパケットデータ構造体の開放
1093void FreeCaptureBlock(struct CAPTUREBLOCK *block){
1094    Free(block);
1095}
1096#endif // BRIDGE_BPF || BRIDGE_PCAP
1097
1098#ifdef  BRIDGE_PCAP
1099// パケット到着のコールバック関数
1100void PcapHandler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
1101{
1102    ETH *e = (ETH*) user;
1103    struct CAPTUREBLOCK *block;
1104    UCHAR *data;
1105   
1106    data = Malloc(h->caplen);
1107    Copy(data, bytes, h->caplen);
1108    block = NewCaptureBlock(data, h->caplen);
1109    LockQueue(e->Queue);
1110    // キューのサイズが限界を超えたらパケットを破棄する。
1111    if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
1112        InsertQueue(e->Queue, block);
1113        e->QueueSize += h->caplen;
1114    }
1115    UnlockQueue(e->Queue);
1116    Cancel(e->Cancel);
1117    return;
1118}
1119
1120
1121// Pcap でのパケットキャプチャの中継用スレッド
1122void PcapThread(THREAD *thread, void *param)
1123{
1124    ETH *e = (ETH*)param;
1125    pcap_t *p = e->Pcap;
1126    int ret;
1127
1128    // 初期化完了を通知
1129    NoticeThreadInit(thread);
1130
1131    // 帰り値 -1:エラー -2:外部からの終了
1132    ret = pcap_loop(p, -1, PcapHandler, (u_char*) e);
1133    if(ret == -1){
1134        e->Socket = INVALID_SOCKET;
1135        pcap_perror(p, "capture");
1136    }
1137    return;
1138}
1139
1140
1141// アダプタを開く (Pcap)
1142ETH *OpenEthPcap(char *name, bool local, bool tapmode, char *tapaddr)
1143{
1144    char errbuf[PCAP_ERRBUF_SIZE];
1145    ETH *e;
1146    pcap_t *p;
1147    CANCEL *c;
1148
1149    // 引数チェック
1150    if (name == NULL || tapmode != false)
1151    {
1152        return NULL;
1153    }
1154   
1155    // エラーメッセージバッファの初期化
1156    errbuf[0] = 0;
1157
1158    // キャプチャデバイスを開く
1159    p = pcap_open_live(name, 65535, (local == false), 1, errbuf);
1160    if(p==NULL)
1161    {
1162        return NULL;
1163    }
1164
1165    // ノンブロックモードに設定
1166    // BSD系OSでは、BPFのselectが正常に動作しないのでブロックさせないとビジーループになる
1167    /*
1168    if(pcap_setnonblock(p, true, errbuf) == -1)
1169    {
1170        Debug("pcap_setnonblock:%s\n",errbuf);
1171        pcap_close(p);
1172        return NULL;
1173    }
1174    */
1175   
1176    e = ZeroMalloc(sizeof(ETH));
1177    e->Name = CopyStr(name);
1178    e->Title = CopyStr(name);
1179    e->Queue = NewQueue();
1180    e->QueueSize = 0;
1181    e->Cancel = NewCancel();
1182    e->IfIndex = -1;
1183    e->Socket = pcap_get_selectable_fd(p);
1184    e->Pcap = p;
1185   
1186    e->CaptureThread = NewThread(PcapThread, e);
1187    WaitThreadInit(e->CaptureThread);
1188
1189    return e;
1190}
1191#endif // BRIDGE_PCAP
1192
1193#ifdef BRIDGE_BPF
1194#ifdef BRIDGE_BPF_THREAD
1195// BPF でのパケットキャプチャの中継用スレッド
1196void BpfThread(THREAD *thread, void *param)
1197{
1198    ETH *e = (ETH*)param;
1199    int fd = e->Socket;
1200    int len;
1201    int rest;   // バッファ中の残りバイト数
1202    UCHAR *next;    //バッファ中の次のパケットの先頭
1203    struct CAPTUREBLOCK *block; // キューに追加するデータ
1204    UCHAR *data;
1205    struct bpf_hdr *hdr;
1206
1207    // バッファを確保
1208    UCHAR *buf = Malloc(e->BufSize);
1209   
1210    // 初期化完了を通知
1211    NoticeThreadInit(thread);
1212
1213    while(1){
1214        // ループの脱出判定
1215        if(e->Socket == INVALID_SOCKET){
1216            break;
1217        }
1218       
1219        rest = read(fd, buf, e->BufSize);
1220        if(rest < 0 && errno != EAGAIN){
1221            // エラー
1222            close(fd);
1223            e->Socket = INVALID_SOCKET;
1224            Free(buf);
1225            Cancel(e->Cancel);
1226            return;
1227        }
1228        next = buf;
1229        LockQueue(e->Queue);
1230        while(rest>0){
1231            // パケットの切り出し
1232            hdr = (struct bpf_hdr*)next;
1233
1234            // Queue中のパケットサイズが限界を超えたらパケットを破棄する
1235            if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
1236                data = Malloc(hdr->bh_caplen);
1237                Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen);
1238                block = NewCaptureBlock(data, hdr->bh_caplen);
1239                InsertQueue(e->Queue, block);
1240                e->QueueSize += hdr->bh_caplen;
1241            }
1242
1243            // 次のパケットの頭出し
1244            rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
1245            next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
1246        }
1247        UnlockQueue(e->Queue);
1248        Cancel(e->Cancel);
1249    }
1250    Free(buf);
1251    Cancel(e->Cancel);
1252    return;
1253}
1254#endif // BRIDGE_BPF_THREAD
1255
1256// アダプタを開く (BPF)
1257ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
1258{
1259    ETH *e;
1260    CANCEL *c;
1261    char devname[MAX_SIZE];
1262    int n = 0;
1263    int fd;
1264    int ret;
1265    UINT bufsize;
1266    struct ifreq ifr;
1267    struct timeval to;
1268   
1269    // 未使用の bpf デバイスを探して開く
1270    do{
1271        Format(devname, sizeof(devname), "/dev/bpf%d", n++);
1272        fd = open (devname, O_RDWR);
1273        if(fd<0){
1274            perror("open");
1275        }
1276    }while(fd < 0 && errno == EBUSY);
1277   
1278    // 開くことが出来るbpfデバイスが無ければエラー
1279    if(fd < 0){
1280        Debug("BPF: No minor number are free.\n");
1281        return NULL;
1282    }
1283   
1284    // バッファサイズを拡大
1285    n = 524288; // なんとなく(libpcapでは32768だった)
1286    while(true){
1287        // バッファサイズを指定
1288        ioctl(fd, BIOCSBLEN, &n);
1289
1290        // ネットワークをバインド
1291        StrCpy(ifr.ifr_name, IFNAMSIZ, name);
1292        ret = ioctl(fd, BIOCSETIF, &ifr);
1293        if(ret < 0){
1294            if(ret == ENOBUFS && n>1500){
1295                // バッファサイズが不適切
1296                // サイズを半分にしてリトライ
1297                // バッファサイズ1500バイト以下でエラーになるのは何かおかしい
1298                n /= 2;
1299                continue;
1300            }
1301            Debug("bpf: binding network failed.\n");
1302            close(fd);
1303            return NULL;
1304        }else{
1305            break;
1306        }
1307    }
1308    bufsize = n;
1309
1310    // プロミスキャスモードに設定
1311    if(local == false){
1312        if (ioctl(fd, BIOCPROMISC, NULL) < 0){
1313            printf("bpf: promisc mode failed.\n");
1314            close(fd);
1315            return NULL;
1316        }
1317    }
1318
1319   
1320    // 即時モードに設定(パケットを受信するとタイムアウトを待たず、すぐにreadがreturnする)
1321    n = 1;
1322    if (ioctl(fd, BIOCIMMEDIATE, &n) < 0){
1323        Debug("BPF: non-block mode failed.\n");
1324        close(fd);
1325        return NULL;
1326    }
1327
1328    // 自分が送信するパケットも受信する
1329    n = 1;
1330    if (ioctl(fd, BIOCGSEESENT, &n) < 0){
1331        Debug("BPF: see sent mode failed.\n");
1332        close(fd);
1333        return NULL;
1334    }
1335
1336
1337    // ヘッダ完全モード(送信するパケットのヘッダも自分で生成する)
1338    n = 1;
1339    if (ioctl(fd, BIOCSHDRCMPLT, &n) < 0){
1340        Debug("BPF: Header complete mode failed.\n");
1341        close(fd);
1342        return NULL;
1343    }
1344   
1345    // read のタイムアウト時間を設定(1秒)
1346    to.tv_sec = 1;
1347    to.tv_usec = 0;
1348    if (ioctl(fd, BIOCSRTIMEOUT, &to) < 0){
1349        Debug("BPF: Read timeout setting failed.\n");
1350        close(fd);
1351        return NULL;
1352    }
1353   
1354    e = ZeroMalloc(sizeof(ETH));
1355    e->Name = CopyStr(name);
1356    e->Title = CopyStr(name);
1357    e->IfIndex = -1;
1358    e->Socket = fd;
1359    e->BufSize = bufsize;
1360
1361#ifdef BRIDGE_BPF_THREAD
1362    e->Queue = NewQueue();
1363    e->QueueSize = 0;
1364    e->Cancel = NewCancel();
1365
1366    // キャプチャ用スレッドの開始
1367    e->CaptureThread = NewThread(BpfThread, e);
1368    WaitThreadInit(e->CaptureThread);
1369
1370#else // BRIDGE_BPF_THREAD
1371    c = NewCancel();
1372    UnixDeletePipe(c->pipe_read, c->pipe_write);
1373    c->pipe_read = c->pipe_write = -1;
1374    c->SpecialFlag = true;
1375    c->pipe_read = fd;
1376    e->Cancel = c;
1377    e->Buffer = Malloc(bufsize);
1378    e->Next = e->Buffer;
1379    e->Rest = 0;
1380
1381    // ノンブロッキングモードに設定
1382    UnixSetSocketNonBlockingMode(fd, true);
1383#endif // BRIDGE_BPF_THREAD
1384
1385    // FreeBSD 用インターフェイス操作用ソケットを作成
1386    e->SocketBsdIf = socket(AF_LOCAL, SOCK_DGRAM, 0);
1387
1388    // MTU の取得
1389    e->InitialMtu = EthGetMtu(e);
1390
1391    return e;
1392}
1393#endif // BRIDGE_BPF
1394
1395// アダプタを開く
1396ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr)
1397{
1398    ETH *ret = NULL;
1399
1400#if     defined(UNIX_LINUX)
1401    ret = OpenEthLinux(name, local, tapmode, tapaddr);
1402#elif   defined(UNIX_SOLARIS)
1403    ret = OpenEthSolaris(name, local, tapmode, tapaddr);
1404#elif   defined(BRIDGE_PCAP)
1405    ret = OpenEthPcap(name, local, tapmode, tapaddr);
1406#elif   defined(BRIDGE_BPF)
1407    ret = OpenEthBpf(name, local, tapmode, tapaddr);
1408#endif
1409
1410    return ret;
1411}
1412
1413typedef struct UNIXTHREAD
1414{
1415    pthread_t thread;
1416    bool finished;
1417} UNIXTHREAD;
1418
1419// アダプタを閉じる
1420void CloseEth(ETH *e)
1421{
1422    // 引数チェック
1423    if (e == NULL)
1424    {
1425        return;
1426    }
1427
1428    if (e->Tap != NULL)
1429    {
1430#ifndef NO_VLAN
1431        FreeTap(e->Tap);
1432#endif  // NO_VLAN
1433    }
1434
1435#ifdef BRIDGE_PCAP
1436    {
1437        struct CAPTUREBLOCK *block;
1438        pcap_breakloop(e->Pcap);
1439        WaitThread(e->CaptureThread, INFINITE);
1440        ReleaseThread(e->CaptureThread);
1441        pcap_close(e->Pcap);
1442        while (block = GetNext(e->Queue)){
1443            Free(block->Buf);
1444            FreeCaptureBlock(block);
1445        }
1446        ReleaseQueue(e->Queue);
1447    }
1448#endif // BRIDGE_PCAP
1449
1450#ifdef BRIDGE_BPF
1451#ifdef BRIDGE_BPF_THREAD
1452    {
1453        struct CAPTUREBLOCK *block;
1454        int fd = e->Socket;
1455        e->Socket = INVALID_SOCKET;
1456        WaitThread(e->CaptureThread, INFINITE);
1457        ReleaseThread(e->CaptureThread);
1458        e->Socket = fd; // 後でcloseするために復帰
1459        while (block = GetNext(e->Queue)){
1460            Free(block->Buf);
1461            FreeCaptureBlock(block);
1462        }
1463        ReleaseQueue(e->Queue);
1464    }
1465#else // BRIDGE_BPF_THREAD
1466    Free(e->Buffer);
1467#endif // BRIDGE_BPF_THREAD
1468#endif // BRIDGE_BPF
1469
1470    ReleaseCancel(e->Cancel);
1471    Free(e->Name);
1472    Free(e->Title);
1473
1474    // MTU の値を元に戻す
1475    EthSetMtu(e, 0);
1476
1477    if (e->Socket != INVALID_SOCKET)
1478    {
1479#if defined(BRIDGE_BPF) || defined(BRIDGE_PCAP) || defined(UNIX_SOLARIS)
1480        close(e->Socket);
1481#else // BRIDGE_PCAP
1482        closesocket(e->Socket);
1483#endif // BRIDGE_PCAP
1484#if defined(BRIDGE_BPF) || defined(UNIX_SOLARIS)
1485        if (e->SocketBsdIf != INVALID_SOCKET)
1486        {
1487            close(e->SocketBsdIf);
1488        }
1489#endif  // BRIDGE_BPF || UNIX_SOLARIS
1490    }
1491
1492    Free(e);
1493}
1494
1495// キャンセルオブジェクトの取得
1496CANCEL *EthGetCancel(ETH *e)
1497{
1498    CANCEL *c;
1499    // 引数チェック
1500    if (e == NULL)
1501    {
1502        return NULL;
1503    }
1504
1505    c = e->Cancel;
1506    AddRef(c->ref);
1507
1508    return c;
1509}
1510
1511// パケットの読み込み
1512UINT EthGetPacket(ETH *e, void **data)
1513{
1514    UINT ret = 0;
1515
1516#if     defined(UNIX_LINUX)
1517    ret = EthGetPacketLinux(e, data);
1518#elif   defined(UNIX_SOLARIS)
1519    ret = EthGetPacketSolaris(e, data);
1520#elif   defined(BRIDGE_PCAP)
1521    ret = EthGetPacketPcap(e, data);
1522#elif   defined(BRIDGE_BPF)
1523    ret = EthGetPacketBpf(e, data);
1524#endif
1525
1526    return ret;
1527}
1528
1529#ifdef  UNIX_LINUX
1530UINT EthGetPacketLinux(ETH *e, void **data)
1531{
1532    int s, ret;
1533    UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE];
1534    // 引数チェック
1535    if (e == NULL || data == NULL)
1536    {
1537        return INFINITE;
1538    }
1539
1540    if (e->Tap != NULL)
1541    {
1542#ifndef NO_VLAN
1543        // tap モード
1544        void *buf;
1545        UINT size;
1546
1547        if (VLanGetNextPacket(e->Tap, &buf, &size) == false)
1548        {
1549            return INFINITE;
1550        }
1551
1552        *data = buf;
1553        return size;
1554#else   // NO_VLAN
1555        return INFINITE;
1556#endif
1557    }
1558
1559    s = e->Socket;
1560
1561    if (s == INVALID_SOCKET)
1562    {
1563        return INFINITE;
1564    }
1565
1566    // 読み込み
1567    ret = read(s, tmp, sizeof(tmp));
1568    if (ret == 0 || (ret == -1 && errno == EAGAIN))
1569    {
1570        // パケット無し
1571        *data = NULL;
1572        return 0;
1573    }
1574    else if (ret == -1 || ret > sizeof(tmp))
1575    {
1576        // エラー
1577        *data = NULL;
1578        e->Socket = INVALID_SOCKET;
1579        return INFINITE;
1580    }
1581    else
1582    {
1583        // パケット読み込み成功
1584        *data = MallocFast(ret);
1585        Copy(*data, tmp, ret);
1586        return ret;
1587    }
1588
1589    return 0;
1590}
1591#endif  // UNIX_LINUX
1592
1593#ifdef  UNIX_SOLARIS
1594UINT EthGetPacketSolaris(ETH *e, void **data)
1595{
1596    UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE];
1597    struct strbuf buf;
1598    int s;
1599    int flags = 0;
1600    int ret;
1601    // 引数チェック
1602    if (e == NULL || data == NULL)
1603    {
1604        return INFINITE;
1605    }
1606
1607    s = e->Socket;
1608    if (s == INVALID_SOCKET)
1609    {
1610        return INFINITE;
1611    }
1612
1613    Zero(&buf, sizeof(buf));
1614    buf.buf = tmp;
1615    buf.maxlen = sizeof(tmp);
1616
1617    ret = getmsg(s, NULL, &buf, &flags);
1618
1619    if (ret < 0 || ret > sizeof(tmp))
1620    {
1621        if (errno == EAGAIN)
1622        {
1623            // パケット無し
1624            *data = NULL;
1625            return 0;
1626        }
1627        // エラー
1628        *data = NULL;
1629        return INFINITE;
1630    }
1631
1632    ret = buf.len;
1633
1634    *data = MallocFast(ret);
1635    Copy(*data, tmp, ret);
1636    return ret;
1637}
1638#endif  // UNIX_SOLARIS
1639
1640#ifdef  BRIDGE_PCAP
1641UINT EthGetPacketPcap(ETH *e, void **data)
1642{
1643    struct CAPTUREBLOCK *block;
1644    UINT size;
1645   
1646    LockQueue(e->Queue);
1647    block = GetNext(e->Queue);
1648    if(block != NULL){
1649        e->QueueSize -= block->Size;
1650    }
1651    UnlockQueue(e->Queue);
1652   
1653    if(block == NULL){
1654        *data = NULL;
1655        if(e->Socket == INVALID_SOCKET){
1656            return INFINITE;
1657        }
1658        return 0;
1659    }
1660   
1661    *data = block->Buf;
1662    size = block->Size;
1663    FreeCaptureBlock(block);
1664   
1665    return size;
1666}
1667#endif // BRIDGE_PCAP
1668
1669#ifdef  BRIDGE_BPF
1670#ifdef BRIDGE_BPF_THREAD
1671UINT EthGetPacketBpf(ETH *e, void **data)
1672{
1673    struct CAPTUREBLOCK *block;
1674    UINT size;
1675   
1676    LockQueue(e->Queue);
1677    block = GetNext(e->Queue);
1678    if(block != NULL){
1679        e->QueueSize -= block->Size;
1680    }
1681    UnlockQueue(e->Queue);
1682   
1683    if(block == NULL){
1684        *data = NULL;
1685        if(e->Socket == INVALID_SOCKET){
1686            return INFINITE;
1687        }
1688        return 0;
1689    }
1690   
1691    *data = block->Buf;
1692    size = block->Size;
1693    FreeCaptureBlock(block);
1694   
1695    return size;
1696}
1697#else // BRIDGE_BPF_THREAD
1698UINT EthGetPacketBpf(ETH *e, void **data)
1699{
1700    struct bpf_hdr *hdr;
1701   
1702    if(e->Rest<=0){
1703        e->Rest = read(e->Socket, e->Buffer, e->BufSize);
1704        if(e->Rest < 0){
1705            *data = NULL;
1706            if(errno != EAGAIN){
1707                // エラー
1708                return INFINITE;
1709            }
1710            // データなし
1711            return 0;
1712        }
1713        e->Next = e->Buffer;
1714    }
1715    // パケットの切り出し
1716    hdr = (struct bpf_hdr*)e->Next;
1717    *data = Malloc(hdr->bh_caplen);
1718    Copy(*data, e->Next+(hdr->bh_hdrlen), hdr->bh_caplen);
1719
1720    // 次のパケットの頭出し
1721    e->Rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
1722    e->Next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
1723   
1724    return hdr->bh_caplen;
1725}
1726#endif // BRIDGE_BPF_THREAD
1727#endif // BRIDGE_BPF
1728
1729
1730// 複数のパケットの書き込み
1731void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)
1732{
1733    UINT i;
1734    // 引数チェック
1735    if (e == NULL || num == 0 || datas == NULL || sizes == NULL)
1736    {
1737        return;
1738    }
1739
1740    for (i = 0;i < num;i++)
1741    {
1742        EthPutPacket(e, datas[i], sizes[i]);
1743    }
1744}
1745
1746// パケットの書き込み
1747void EthPutPacket(ETH *e, void *data, UINT size)
1748{
1749    int s, ret;
1750    // 引数チェック
1751    if (e == NULL || data == NULL)
1752    {
1753        return;
1754    }
1755    if (size < 14 || size > MAX_PACKET_SIZE)
1756    {
1757        Free(data);
1758        return;
1759    }
1760
1761    if (e->Tap != NULL)
1762    {
1763#ifndef NO_VLAN
1764        // tap モード
1765        VLanPutPacket(e->Tap, data, size);
1766#endif  // NO_VLAN
1767        return;
1768    }
1769
1770    s = e->Socket;
1771
1772    if (s == INVALID_SOCKET)
1773    {
1774        Free(data);
1775        return;
1776    }
1777
1778    // 書き込み
1779#ifdef BRIDGE_PCAP
1780    ret = pcap_inject(e->Pcap, data, size);
1781    if( ret == -1 ){
1782#ifdef _DEBUG
1783        pcap_perror(e->Pcap, "inject");
1784#endif // _DEBUG
1785        Debug("EthPutPacket: ret:%d size:%d\n", ret, size);
1786    }
1787#else // BRIDGE_PCAP
1788    ret = write(s, data, size);
1789    if (ret<0)
1790    {
1791        Debug("EthPutPacket: ret:%d errno:%d  size:%d\n", ret, errno, size);
1792    }
1793#endif //BRIDGE_PCAP
1794   
1795    Free(data);
1796}
1797
1798#endif  // BRIDGE_C
1799
1800
Note: See TracBrowser for help on using the repository browser.