1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Cedar Communication Module
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100 
101 
102 // BridgeUnix.c
103 // Ethernet Bridge Program (for UNIX)
104 //#define	BRIDGE_C
105 //#define	UNIX_LINUX
106 
107 #include <GlobalConst.h>
108 
109 #ifdef	BRIDGE_C
110 
111 #include <stdio.h>
112 #include <stdlib.h>
113 #include <string.h>
114 #include <wchar.h>
115 #include <stdarg.h>
116 #include <time.h>
117 #include <errno.h>
118 #include <Mayaqua/Mayaqua.h>
119 #include <Cedar/Cedar.h>
120 
121 #ifdef UNIX_SOLARIS
122 #include <sys/sockio.h>
123 #endif
124 
125 #ifdef BRIDGE_PCAP
126 #include <pcap.h>
127 #endif // BRIDGE_PCAP
128 
129 #ifdef BRIDGE_BPF
130 #include <sys/ioctl.h>
131 #include <net/bpf.h>
132 #include <net/if_types.h>
133 #include <net/if_dl.h>
134 #include <ifaddrs.h>
135 #endif // BRIDGE_BPF
136 
137 #ifdef	UNIX_LINUX
138 struct my_tpacket_auxdata
139 {
140 	UINT tp_status;
141 	UINT tp_len;
142 	UINT tp_snaplen;
143 	USHORT tp_mac;
144 	USHORT tp_net;
145 	USHORT tp_vlan_tci;
146 	USHORT tp_vlan_tpid;
147 };
148 #define MY_TP_STATUS_VLAN_VALID (1 << 4)
149 #define MY_TP_STATUS_VLAN_TPID_VALID (1 << 6)
150 #define	MY_PACKET_AUXDATA 8
151 #endif	// UNIX_LINUX
152 
153 static LIST *eth_offload_list = NULL;
154 
155 // Initialize
InitEth()156 void InitEth()
157 {
158 	eth_offload_list = NewList(NULL);
159 }
160 
161 // Free
FreeEth()162 void FreeEth()
163 {
164 	if (eth_offload_list != NULL)
165 	{
166 		FreeStrList(eth_offload_list);
167 		eth_offload_list = NULL;
168 	}
169 }
170 
171 // Check whether interface description string of Ethernet device can be retrieved in this system
EthIsInterfaceDescriptionSupportedUnix()172 bool EthIsInterfaceDescriptionSupportedUnix()
173 {
174 	bool ret = false;
175 	DIRLIST *d = EnumDir("/etc/sysconfig/networking/devices/");
176 
177 	if (d == NULL)
178 	{
179 		return false;
180 	}
181 
182 	if (d->NumFiles >= 1)
183 	{
184 		ret = true;
185 	}
186 
187 	FreeDir(d);
188 
189 	return ret;
190 }
191 
192 // Get interface description string
EthGetInterfaceDescriptionUnix(char * name,char * str,UINT size)193 bool EthGetInterfaceDescriptionUnix(char *name, char *str, UINT size)
194 {
195 	char tmp[MAX_SIZE];
196 	bool ret = false;
197 	BUF *b;
198 	// Validate arguments
199 	if (name == NULL || str == NULL)
200 	{
201 		return false;
202 	}
203 
204 	StrCpy(str, size, name);
205 
206 	Format(tmp, sizeof(tmp), "/etc/sysconfig/networking/devices/ifcfg-%s", name);
207 
208 	b = ReadDump(tmp);
209 	if (b != NULL)
210 	{
211 		char *line = CfgReadNextLine(b);
212 
213 		if (IsEmptyStr(line) == false)
214 		{
215 			if (StartWith(line, "#"))
216 			{
217 				char tmp[MAX_SIZE];
218 
219 				StrCpy(tmp, sizeof(tmp), line + 1);
220 
221 				Trim(tmp);
222 				tmp[60] = 0;
223 
224 				StrCpy(str, size, tmp);
225 
226 				ret = true;
227 			}
228 		}
229 
230 		Free(line);
231 
232 		FreeBuf(b);
233 	}
234 
235 	return ret;
236 }
237 
238 // Open raw socket
UnixEthOpenRawSocket()239 int UnixEthOpenRawSocket()
240 {
241 #ifdef	UNIX_LINUX
242 	int s;
243 
244 	s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
245 	if (s < 0)
246 	{
247 		return INVALID_SOCKET;
248 	}
249 	else
250 	{
251 		return s;
252 	}
253 #else	// UNIX_LINUX
254 	return -1;
255 #endif	// UNIX_LINUX
256 }
257 
258 // Is Ethernet device control supported?
IsEthSupported()259 bool IsEthSupported()
260 {
261 	bool ret = false;
262 
263 #if		defined(UNIX_LINUX)
264 	ret = IsEthSupportedLinux();
265 #elif	defined(UNIX_SOLARIS)
266 	ret = IsEthSupportedSolaris();
267 #elif	defined(BRIDGE_PCAP)
268 	ret = true;
269 #elif	defined(BRIDGE_BPF)
270 	ret = true;
271 #endif
272 	return ret;
273 }
274 
275 #ifdef	UNIX_LINUX
IsEthSupportedLinux()276 bool IsEthSupportedLinux()
277 {
278 	int s;
279 
280 	// Try to open a raw socket
281 	s = UnixEthOpenRawSocket();
282 	if (s == INVALID_SOCKET)
283 	{
284 		// fail
285 		return false;
286 	}
287 
288 	// success
289 	closesocket(s);
290 
291 	return true;
292 }
293 #endif	// UNIX_LINUX
294 
295 #ifdef	UNIX_SOLARIS
IsEthSupportedSolaris()296 bool IsEthSupportedSolaris()
297 {
298 	return true;
299 }
300 #endif	// UNIX_SOLARIS
301 
302 #ifdef	UNIX_SOLARIS
303 // Get Ethernet device list on Solaris
GetEthListSolaris()304 TOKEN_LIST *GetEthListSolaris()
305 {
306 	TOKEN_LIST *t;
307 	int i, s;
308 	LIST *o;
309 
310 
311 	o = NewListFast(CompareStr);
312 	s = socket(AF_INET, SOCK_DGRAM, 0);
313 	if (s != INVALID_SOCKET)
314 	{
315 		struct lifnum lifn;
316 		lifn.lifn_family = AF_INET;
317 		lifn.lifn_flags = 0;
318 		if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) >= 0)
319 		{
320 			struct lifconf lifc;
321 			struct lifreq *buf;
322 			UINT numifs;
323 			UINT bufsize;
324 
325 			numifs = lifn.lifn_count;
326 			Debug("NumIFs:%d\n",numifs);
327 			bufsize = numifs * sizeof(struct lifreq);
328 			buf = Malloc(bufsize);
329 
330 			lifc.lifc_family = AF_INET;
331 			lifc.lifc_flags = 0;
332 			lifc.lifc_len = bufsize;
333 			lifc.lifc_buf = (char*) buf;
334 			if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) >= 0)
335 			{
336 				for (i = 0; i<numifs; i++)
337 				{
338 					if(StartWith(buf[i].lifr_name, "lo") == false){
339 						Add(o, CopyStr(buf[i].lifr_name));
340 					}
341 				}
342 			}
343 			Free(buf);
344 		}
345 		closesocket(s);
346 	}
347 
348 	Sort(o);
349 
350 	t = ZeroMalloc(sizeof(TOKEN_LIST));
351 	t->NumTokens = LIST_NUM(o);
352 	t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
353 
354 	for (i = 0;i < LIST_NUM(o);i++)
355 	{
356 		char *name = LIST_DATA(o, i);
357 		t->Token[i] = name;
358 	}
359 
360 	ReleaseList(o);
361 
362 	return t;
363 }
364 #endif	// UNIX_SOLARIS
365 
366 #ifdef	UNIX_LINUX
367 // Get Ethernet device list on Linux
GetEthListLinux(bool enum_normal,bool enum_rawip)368 TOKEN_LIST *GetEthListLinux(bool enum_normal, bool enum_rawip)
369 {
370 	struct ifreq ifr;
371 	TOKEN_LIST *t;
372 	UINT i, n;
373 	int s;
374 	LIST *o;
375 	char name[MAX_SIZE];
376 
377 	if (enum_normal == false && enum_rawip)
378 	{
379 		return ParseToken(BRIDGE_SPECIAL_IPRAW_NAME, NULL);
380 	}
381 
382 	o = NewListFast(CompareStr);
383 
384 	s = UnixEthOpenRawSocket();
385 	if (s != INVALID_SOCKET)
386 	{
387 		n = 0;
388 		for (i = 0;;i++)
389 		{
390 			Zero(&ifr, sizeof(ifr));
391 			ifr.ifr_ifindex = i;
392 
393 			if (ioctl(s, SIOCGIFNAME, &ifr) >= 0)
394 			{
395 				n = 0;
396 				StrCpy(name, sizeof(name), ifr.ifr_name);
397 
398 				Zero(&ifr, sizeof(ifr));
399 				StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
400 				if (ioctl(s, SIOCGIFHWADDR, &ifr) >= 0)
401 				{
402 					UINT type = ifr.ifr_hwaddr.sa_family;
403 					if (type == 1 || type == 2 || type == 6 || type == 800 || type == 801)
404 					{
405 						if (IsInListStr(o, name) == false)
406 						{
407 							if (StartWith(name, "tap_") == false)
408 							{
409 								Add(o, CopyStr(name));
410 							}
411 						}
412 					}
413 				}
414 			}
415 			else
416 			{
417 				n++;
418 				if (n >= 64)
419 				{
420 					break;
421 				}
422 			}
423 		}
424 		closesocket(s);
425 	}
426 
427 	Sort(o);
428 
429 	t = ZeroMalloc(sizeof(TOKEN_LIST));
430 	t->NumTokens = LIST_NUM(o) + (enum_rawip ? 1 : 0);
431 	t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
432 
433 	for (i = 0;i < LIST_NUM(o);i++)
434 	{
435 		char *name = LIST_DATA(o, i);
436 		t->Token[i] = name;
437 	}
438 
439 	if (enum_rawip)
440 	{
441 		t->Token[t->NumTokens - 1] = CopyStr(BRIDGE_SPECIAL_IPRAW_NAME);
442 	}
443 
444 	ReleaseList(o);
445 
446 	return t;
447 }
448 #endif	// UNIX_LINUX
449 
450 #ifdef BRIDGE_PCAP
451 // Ethernet device list by Pcap API
GetEthListPcap()452 TOKEN_LIST *GetEthListPcap()
453 {
454 	pcap_if_t *alldevs;
455 	char errbuf[PCAP_ERRBUF_SIZE];
456 	LIST *o;
457 	TOKEN_LIST *t;
458 	int i;
459 
460 	o = NewListFast(CompareStr);
461 
462 	if( pcap_findalldevs(&alldevs,errbuf) != -1)
463 	{
464 		pcap_if_t *dev = alldevs;
465 		while(dev != NULL)
466 		{
467 			pcap_t *p;
468 			// Device type will be unknown until open the device?
469 			p = pcap_open_live(dev->name, 0, false, 0, errbuf);
470 			if(p != NULL)
471 			{
472 				int datalink = pcap_datalink(p);
473 	//			Debug("type:%s\n",pcap_datalink_val_to_name(datalink));
474 				pcap_close(p);
475 				if(datalink == DLT_EN10MB){
476 					// Enumerate only Ethernet type device
477 					Add(o, CopyStr(dev->name));
478 				}
479 			}
480 			dev = dev->next;
481 		}
482 		pcap_freealldevs(alldevs);
483 	}
484 
485 	Sort(o);
486 	t = ZeroMalloc(sizeof(TOKEN_LIST));
487 	t->NumTokens = LIST_NUM(o);
488 	t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
489 	for (i = 0;i < LIST_NUM(o);i++)
490 	{
491 		t->Token[i] = LIST_DATA(o, i);
492 	}
493 	ReleaseList(o);
494 	return t;
495 }
496 #endif // BRIDGE_PCAP
497 
498 #ifdef BRIDGE_BPF
499 // Ethernet device list by BPF API
GetEthListBpf()500 TOKEN_LIST *GetEthListBpf()
501 {
502 	struct ifaddrs *ifadrs;
503 	struct sockaddr_dl *sockadr;
504 	LIST *o;
505 	TOKEN_LIST *t;
506 	int i;
507 
508 	o = NewListFast(CompareStr);
509 
510 	// Enumerate network devices
511 	if(getifaddrs( &ifadrs ) == 0)
512 	{
513 		struct ifaddrs *ifadr = ifadrs;
514 		while(ifadr)
515 		{
516 			sockadr = (struct sockaddr_dl*)ifadr->ifa_addr;
517 			if(sockadr->sdl_family == AF_LINK && sockadr->sdl_type == IFT_ETHER)
518 			{
519 				// Is this Ethernet device?
520 				if(!IsInListStr(o,ifadr->ifa_name))
521 				{
522 					// Ignore the foregoing device (for device which have multiple MAC address)
523 					Add(o, CopyStr(ifadr->ifa_name));
524 				}
525 			}
526 			ifadr = ifadr -> ifa_next;
527 		}
528 		freeifaddrs(ifadrs);
529 	}
530 
531 	Sort(o);
532 	t = ZeroMalloc(sizeof(TOKEN_LIST));
533 	t->NumTokens = LIST_NUM(o);
534 	t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens);
535 	for (i = 0;i < LIST_NUM(o);i++)
536 	{
537 		t->Token[i] = LIST_DATA(o, i);
538 	}
539 	ReleaseList(o);
540 	return t;
541 }
542 #endif // BRIDGE_BPF
543 
544 // Enumerate Ethernet devices
GetEthList()545 TOKEN_LIST *GetEthList()
546 {
547 	return GetEthListEx(NULL, true, false);
548 }
GetEthListEx(UINT * total_num_including_hidden,bool enum_normal,bool enum_rawip)549 TOKEN_LIST *GetEthListEx(UINT *total_num_including_hidden, bool enum_normal, bool enum_rawip)
550 {
551 	TOKEN_LIST *t = NULL;
552 
553 #if	defined(UNIX_LINUX)
554 	t = GetEthListLinux(enum_normal, enum_rawip);
555 #elif	defined(UNIX_SOLARIS)
556 	t = GetEthListSolaris();
557 #elif	defined(BRIDGE_PCAP)
558 	t = GetEthListPcap();
559 #elif	defined(BRIDGE_BPF)
560 	t = GetEthListBpf();
561 #endif
562 
563 	return t;
564 }
565 
566 #ifdef	UNIX_LINUX
567 // Open Ethernet device (Linux)
OpenEthLinux(char * name,bool local,bool tapmode,char * tapaddr)568 ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr)
569 {
570 	ETH *e;
571 	struct ifreq ifr;
572 	struct sockaddr_ll addr;
573 	int s;
574 	int index;
575 	bool aux_ok = false;
576 	CANCEL *c;
577 	// Validate arguments
578 	if (name == NULL)
579 	{
580 		return NULL;
581 	}
582 
583 	if (StrCmpi(name, BRIDGE_SPECIAL_IPRAW_NAME) == 0)
584 	{
585 		return OpenEthLinuxIpRaw();
586 	}
587 
588 	if (tapmode)
589 	{
590 #ifndef	NO_VLAN
591 		// In tap mode
592 		VLAN *v = NewTap(name, tapaddr);
593 		if (v == NULL)
594 		{
595 			return NULL;
596 		}
597 
598 		e = ZeroMalloc(sizeof(ETH));
599 		e->Name = CopyStr(name);
600 		e->Title = CopyStr(name);
601 		e->Cancel = VLanGetCancel(v);
602 		e->IfIndex = 0;
603 		e->Socket = INVALID_SOCKET;
604 		e->Tap = v;
605 
606 		return e;
607 #else	// NO_VLAN
608 		return NULL;
609 #endif	// NO_VLAN
610 	}
611 
612 	s = UnixEthOpenRawSocket();
613 	if (s == INVALID_SOCKET)
614 	{
615 		return NULL;
616 	}
617 
618 	Zero(&ifr, sizeof(ifr));
619 	StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
620 
621 	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0)
622 	{
623 		closesocket(s);
624 		return NULL;
625 	}
626 
627 	index = ifr.ifr_ifindex;
628 
629 	Zero(&addr, sizeof(addr));
630 	addr.sll_family = PF_PACKET;
631 	addr.sll_protocol = htons(ETH_P_ALL);
632 	addr.sll_ifindex = index;
633 
634 	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
635 	{
636 		closesocket(s);
637 		return NULL;
638 	}
639 
640 	if (local == false)
641 	{
642 		// Enable promiscious mode
643 		Zero(&ifr, sizeof(ifr));
644 		StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name);
645 		if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0)
646 		{
647 			// Failed
648 			closesocket(s);
649 			return NULL;
650 		}
651 
652 		ifr.ifr_flags |= IFF_PROMISC;
653 
654 		if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0)
655 		{
656 			// Failed
657 			closesocket(s);
658 			return NULL;
659 		}
660 	}
661 
662 	if (true)
663 	{
664 		int val = 1;
665 		int ss_ret = setsockopt(s, SOL_PACKET, MY_PACKET_AUXDATA, &val, sizeof(val));
666 
667 		if (ss_ret < 0)
668 		{
669 			Debug("eth(%s): setsockopt: PACKET_AUXDATA failed.\n", name);
670 		}
671 		else
672 		{
673 			Debug("eth(%s): setsockopt: PACKET_AUXDATA ok.\n", name);
674 			aux_ok = true;
675 		}
676 	}
677 
678 	e = ZeroMalloc(sizeof(ETH));
679 	e->Name = CopyStr(name);
680 	e->Title = CopyStr(name);
681 	e->IfIndex = index;
682 	e->Socket = s;
683 
684 	e->Linux_IsAuxDataSupported = aux_ok;
685 
686 	c = NewCancel();
687 	UnixDeletePipe(c->pipe_read, c->pipe_write);
688 	c->pipe_read = c->pipe_write = -1;
689 
690 	UnixSetSocketNonBlockingMode(s, true);
691 
692 	c->SpecialFlag = true;
693 	c->pipe_read = s;
694 
695 	e->Cancel = c;
696 
697 	// Get MTU
698 	e->InitialMtu = EthGetMtu(e);
699 
700 	if (tapmode == false)
701 	{
702 		if (GetGlobalServerFlag(GSF_LOCALBRIDGE_NO_DISABLE_OFFLOAD) == false)
703 		{
704 			bool b = false;
705 
706 			LockList(eth_offload_list);
707 			{
708 				if (IsInListStr(eth_offload_list, name) == false)
709 				{
710 					b = true;
711 
712 					Add(eth_offload_list, CopyStr(name));
713 				}
714 			}
715 			UnlockList(eth_offload_list);
716 
717 			if (b)
718 			{
719 				// Disable hardware offloading
720 				UnixDisableInterfaceOffload(name);
721 			}
722 		}
723 	}
724 
725 	return e;
726 }
727 #endif	// UNIX_LINUX
728 
729 // Get the MTU value
EthGetMtu(ETH * e)730 UINT EthGetMtu(ETH *e)
731 {
732 #if	defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
733 	UINT ret = 0;
734 #ifdef	UNIX_SOLARIS
735 	struct lifreq ifr;
736 #else	// UNIX_SOLARIS
737 	struct ifreq ifr;
738 #endif	// UNIX_SOLARIS
739 	int s;
740 	// Validate arguments
741 	if (e == NULL || e->Tap != NULL)
742 	{
743 		return 0;
744 	}
745 	if (e->IsRawIpMode)
746 	{
747 		return 0;
748 	}
749 
750 	if (e->CurrentMtu != 0)
751 	{
752 		return e->CurrentMtu;
753 	}
754 
755 #if	defined(UNIX_BSD) || defined(UNIX_SOLARIS)
756 	s = e->SocketBsdIf;
757 #else	// defined(UNIX_BSD) || defined(UNIX_SOLARIS)
758 	s = e->Socket;
759 #endif	// defined(UNIX_BSD) || defined(UNIX_SOLARIS)
760 
761 	Zero(&ifr, sizeof(ifr));
762 
763 #ifdef	UNIX_SOLARIS
764 	StrCpy(ifr.lifr_name, sizeof(ifr.lifr_name), e->Name);
765 #else	// UNIX_SOLARIS
766 	StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), e->Name);
767 #endif	// UNIX_SOLARIS
768 
769 #ifdef	UNIX_SOLARIS
770 	if (ioctl(s, SIOCGLIFMTU, &ifr) < 0)
771 	{
772 		// failed
773 		return 0;
774 	}
775 #else	// UNIX_SOLARIS
776 	if (ioctl(s, SIOCGIFMTU, &ifr) < 0)
777 	{
778 		// failed
779 		return 0;
780 	}
781 #endif	// UNIX_SOLARIS
782 
783 #ifdef	UNIX_SOLARIS
784 	ret = ifr.lifr_mtu + 14;
785 #else	// UNIX_SOLARIS
786 	ret = ifr.ifr_mtu + 14;
787 #endif	// UNIX_SOLARIS
788 
789 	e->CurrentMtu = ret;
790 
791 	Debug("%s: GetMtu: %u\n", e->Name, ret);
792 
793 	return ret;
794 #else	// defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
795 	return 0;
796 #endif	// defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
797 }
798 
799 // Set the MTU value
EthSetMtu(ETH * e,UINT mtu)800 bool EthSetMtu(ETH *e, UINT mtu)
801 {
802 #if	defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
803 	UINT ret = 0;
804 #ifdef	UNIX_SOLARIS
805 	struct lifreq ifr;
806 #else	// UNIX_SOLARIS
807 	struct ifreq ifr;
808 #endif	// UNIX_SOLARIS
809 	int s;
810 	// Validate arguments
811 	if (e == NULL || e->Tap != NULL || (mtu > 1 && mtu < 1514))
812 	{
813 		return false;
814 	}
815 	if (mtu == 0 && e->InitialMtu == 0)
816 	{
817 		return false;
818 	}
819 	if (e->IsRawIpMode)
820 	{
821 		return false;
822 	}
823 
824 	if (mtu == 0)
825 	{
826 		// Restore initial MTU value when parameter mtu == 0
827 		mtu = e->InitialMtu;
828 	}
829 
830 #if	defined(UNIX_BSD) || defined(UNIX_SOLARIS)
831 	s = e->SocketBsdIf;
832 #else	// defined(UNIX_BSD) || defined(UNIX_SOLARIS)
833 	s = e->Socket;
834 #endif	// defined(UNIX_BSD) || defined(UNIX_SOLARIS)
835 
836 	if (e->CurrentMtu == mtu)
837 	{
838 		// No need to change
839 		return true;
840 	}
841 
842 	Zero(&ifr, sizeof(ifr));
843 
844 #ifdef	UNIX_SOLARIS
845 	StrCpy(ifr.lifr_name, sizeof(ifr.lifr_name), e->Name);
846 	ifr.lifr_mtu = mtu - 14;
847 #else	// UNIX_SOLARIS
848 	StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), e->Name);
849 	ifr.ifr_mtu = mtu - 14;
850 #endif	// UNIX_SOLARIS
851 
852 #ifdef	UNIX_SOLARIS
853 	if (ioctl(s, SIOCSLIFMTU, &ifr) < 0)
854 	{
855 		// Failed
856 		return false;
857 	}
858 #else	// UNIX_SOLARIS
859 	if (ioctl(s, SIOCSIFMTU, &ifr) < 0)
860 	{
861 		// Failed
862 		return false;
863 	}
864 #endif	// UNIX_SOLARIS
865 
866 	e->CurrentMtu = mtu;
867 
868 	Debug("%s: SetMtu: %u\n", e->Name, mtu);
869 
870 	return true;
871 #else	// defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
872 	return false;
873 #endif	// defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
874 }
875 
876 // Is changing MTU supported?
EthIsChangeMtuSupported(ETH * e)877 bool EthIsChangeMtuSupported(ETH *e)
878 {
879 #if	defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
880 	// Validate arguments
881 	if (e == NULL || e->Tap != NULL)
882 	{
883 		return false;
884 	}
885 
886 	if (e->IsRawIpMode)
887 	{
888 		return false;
889 	}
890 
891 	return true;
892 #else	// defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
893 	return false;
894 #endif	// defined(UNIX_LINUX) || defined(UNIX_BSD) || defined(UNIX_SOLARIS)
895 }
896 
897 #ifdef	UNIX_SOLARIS
898 // Open Ethernet adapter (Solaris)
OpenEthSolaris(char * name,bool local,bool tapmode,char * tapaddr)899 ETH *OpenEthSolaris(char *name, bool local, bool tapmode, char *tapaddr)
900 {
901 	char devname[MAX_SIZE];
902 	UINT devid;
903 	int fd;
904 	ETH *e;
905 	CANCEL *c;
906 	struct strioctl sioc;
907 
908 	// Validate arguments
909 	if (name == NULL || tapmode != false)
910 	{
911 		return NULL;
912 	}
913 
914 	// Parse device name
915 	if (ParseUnixEthDeviceName(devname, sizeof(devname), &devid, name) == false)
916 	{
917 		return NULL;
918 	}
919 
920 	// Open the device
921 	fd = open(devname, O_RDWR);
922 	if (fd == -1)
923 	{
924 		// Failed
925 		return NULL;
926 	}
927 
928 	// Attach to the device
929 	if (DlipAttatchRequest(fd, devid) == false)
930 	{
931 		// Failed
932 		close(fd);
933 		return NULL;
934 	}
935 
936 	// Verify ACK message
937 	if (DlipReceiveAck(fd) == false)
938 	{
939 		// Failed
940 		close(fd);
941 		return NULL;
942 	}
943 
944 	// Bind to SAP
945 	if (DlipBindRequest(fd) == false)
946 	{
947 		// Failed
948 		close(fd);
949 		return NULL;
950 	}
951 
952 	// Verify ACK message
953 	if (DlipReceiveAck(fd) == false)
954 	{
955 		// Failed
956 		close(fd);
957 		return NULL;
958 	}
959 
960 	// Set to ignore SAP and promiscuous mode
961 	if (DlipPromiscuous(fd, DL_PROMISC_SAP) == false)
962 	{
963 		// Failed
964 		close(fd);
965 		return NULL;
966 	}
967 
968 	// Verify ACK message
969 	if (DlipReceiveAck(fd) == false)
970 	{
971 		// Failed
972 		close(fd);
973 		return NULL;
974 	}
975 
976 	// Set to the mode to receive self sending packet
977 	if (DlipPromiscuous(fd, DL_PROMISC_PHYS) == false)
978 	{
979 		// Failed
980 		close(fd);
981 		return NULL;
982 	}
983 
984 	// Verify ACK message
985 	if (DlipReceiveAck(fd) == false)
986 	{
987 		// Failed
988 		close(fd);
989 		return NULL;
990 	}
991 
992 	// Set to raw mode
993 	sioc.ic_cmd = DLIOCRAW;
994 	sioc.ic_timout = -1;
995 	sioc.ic_len = 0;
996 	sioc.ic_dp = NULL;
997 	if (ioctl(fd, I_STR, &sioc) < 0)
998 	{
999 		// Failed
1000 		close(fd);
1001 		return NULL;
1002 	}
1003 
1004 	if (ioctl(fd, I_FLUSH, FLUSHR) < 0)
1005 	{
1006 		// Failed
1007 		close(fd);
1008 		return NULL;
1009 	}
1010 
1011 	e = ZeroMalloc(sizeof(ETH));
1012 	e->Name = CopyStr(name);
1013 	e->Title = CopyStr(name);
1014 
1015 	c = NewCancel();
1016 	UnixDeletePipe(c->pipe_read, c->pipe_write);
1017 	c->pipe_read = c->pipe_write = -1;
1018 
1019 	c->SpecialFlag = true;
1020 	c->pipe_read = fd;
1021 
1022 	e->Cancel = c;
1023 
1024 	e->IfIndex = -1;
1025 	e->Socket = fd;
1026 
1027 	UnixSetSocketNonBlockingMode(fd, true);
1028 
1029 	// Get control interface
1030 	e->SocketBsdIf = socket(AF_INET, SOCK_DGRAM, 0);
1031 
1032 	// Get MTU value
1033 	e->InitialMtu = EthGetMtu(e);
1034 
1035 	return e;
1036 }
1037 
1038 // Set to promiscuous mode
DlipPromiscuous(int fd,UINT level)1039 bool DlipPromiscuous(int fd, UINT level)
1040 {
1041 	dl_promiscon_req_t req;
1042 	struct strbuf ctl;
1043 	int flags;
1044 	// Validate arguments
1045 	if (fd == -1)
1046 	{
1047 		return false;
1048 	}
1049 
1050 	Zero(&req, sizeof(req));
1051 	req.dl_primitive = DL_PROMISCON_REQ;
1052 	req.dl_level = level;
1053 
1054 	Zero(&ctl, sizeof(ctl));
1055 	ctl.maxlen = 0;
1056 	ctl.len = sizeof(req);
1057 	ctl.buf = (char *)&req;
1058 
1059 	flags = 0;
1060 
1061 	if (putmsg(fd, &ctl, NULL, flags) < 0)
1062 	{
1063 		return false;
1064 	}
1065 
1066 	return true;
1067 }
1068 
1069 // Bind to a SAP
DlipBindRequest(int fd)1070 bool DlipBindRequest(int fd)
1071 {
1072 	dl_bind_req_t	req;
1073 	struct strbuf ctl;
1074 
1075 	if (fd == -1)
1076 	{
1077 		return false;
1078 	}
1079 
1080 	Zero(&req, sizeof(req));
1081 	req.dl_primitive = DL_BIND_REQ;
1082 	req.dl_service_mode = DL_CLDLS;
1083 	req.dl_sap = 0;
1084 
1085 	Zero(&ctl, sizeof(ctl));
1086 	ctl.maxlen = 0;
1087 	ctl.len = sizeof(req);
1088 	ctl.buf = (char *)&req;
1089 
1090 	if (putmsg(fd, &ctl, NULL, 0) < 0)
1091 	{
1092 		return false;
1093 	}
1094 	return true;
1095 }
1096 
1097 // Attach to the device
DlipAttatchRequest(int fd,UINT devid)1098 bool DlipAttatchRequest(int fd, UINT devid)
1099 {
1100 	dl_attach_req_t req;
1101 	struct strbuf ctl;
1102 	int flags;
1103 	// Validate arguments
1104 	if (fd == -1)
1105 	{
1106 		return false;
1107 	}
1108 
1109 	Zero(&req, sizeof(req));
1110 	req.dl_primitive = DL_ATTACH_REQ;
1111 	req.dl_ppa = devid;
1112 
1113 	Zero(&ctl, sizeof(ctl));
1114 	ctl.maxlen = 0;
1115 	ctl.len = sizeof(req);
1116 	ctl.buf = (char *)&req;
1117 
1118 	flags = 0;
1119 
1120 	if (putmsg(fd, &ctl, NULL, flags) < 0)
1121 	{
1122 		return false;
1123 	}
1124 
1125 	return true;
1126 }
1127 
1128 // Verify the ACK message
DlipReceiveAck(int fd)1129 bool DlipReceiveAck(int fd)
1130 {
1131 	union DL_primitives *dlp;
1132 	struct strbuf ctl;
1133 	int flags = 0;
1134 	char *buf;
1135 	// Validate arguments
1136 	if (fd == -1)
1137 	{
1138 		return false;
1139 	}
1140 
1141 	buf = MallocFast(SOLARIS_MAXDLBUF);
1142 
1143 	Zero(&ctl, sizeof(ctl));
1144 	ctl.maxlen = SOLARIS_MAXDLBUF;
1145 	ctl.len = 0;
1146 	ctl.buf = buf;
1147 
1148 	if (getmsg(fd, &ctl, NULL, &flags) < 0)
1149 	{
1150 		return false;
1151 	}
1152 
1153 	dlp = (union DL_primitives *)ctl.buf;
1154 	if (dlp->dl_primitive != (UINT)DL_OK_ACK && dlp->dl_primitive != (UINT)DL_BIND_ACK)
1155 	{
1156 		Free(buf);
1157 		return false;
1158 	}
1159 
1160 	Free(buf);
1161 
1162 	return true;
1163 }
1164 
1165 #endif	// UNIX_SOLARIS
1166 
1167 // Separate UNIX device name string into device name and id number
ParseUnixEthDeviceName(char * dst_devname,UINT dst_devname_size,UINT * dst_devid,char * src_name)1168 bool ParseUnixEthDeviceName(char *dst_devname, UINT dst_devname_size, UINT *dst_devid, char *src_name)
1169 {
1170 	UINT len, i, j;
1171 
1172 	// Validate arguments
1173 	if (dst_devname == NULL || dst_devid == NULL || src_name == NULL)
1174 	{
1175 		return false;
1176 	}
1177 
1178 	len = strlen(src_name);
1179 	// Check string length
1180 	if(len == 0)
1181 	{
1182 		return false;
1183 	}
1184 
1185 	for (i = len-1; i+1 != 0; i--)
1186 	{
1187 		// Find last non-numeric character
1188 		if (src_name[i] < '0' || '9' < src_name[i])
1189 		{
1190 			// last character must be a number
1191 			if(src_name[i+1]==0)
1192 			{
1193 				return false;
1194 			}
1195 			*dst_devid = ToInt(src_name + i + 1);
1196 			StrCpy(dst_devname, dst_devname_size, "/dev/");
1197 			for (j = 0; j<i+1 && j<dst_devname_size-6; j++)
1198 			{
1199 				dst_devname[j+5] = src_name[j];
1200 			}
1201 			dst_devname[j+5]=0;
1202 			return true;
1203 		}
1204 	}
1205 	// All characters in the string was numeric: error
1206 	return false;
1207 }
1208 
1209 #if defined(BRIDGE_BPF) || defined(BRIDGE_PCAP)
1210 // Initialize captured packet data structure
NewCaptureBlock(UCHAR * data,UINT size)1211 struct CAPTUREBLOCK *NewCaptureBlock(UCHAR *data, UINT size){
1212 	struct CAPTUREBLOCK *block = Malloc(sizeof(struct CAPTUREBLOCK));
1213 	block->Buf = data;
1214 	block->Size = size;
1215 	return block;
1216 }
1217 
1218 // Free captured packet data structure
FreeCaptureBlock(struct CAPTUREBLOCK * block)1219 void FreeCaptureBlock(struct CAPTUREBLOCK *block){
1220 	Free(block);
1221 }
1222 #endif // BRIDGE_BPF || BRIDGE_PCAP
1223 
1224 #ifdef	BRIDGE_PCAP
1225 // Callback function to receive arriving packet (Pcap)
PcapHandler(u_char * user,const struct pcap_pkthdr * h,const u_char * bytes)1226 void PcapHandler(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
1227 {
1228 	ETH *e = (ETH*) user;
1229 	struct CAPTUREBLOCK *block;
1230 	UCHAR *data;
1231 
1232 	data = Malloc(h->caplen);
1233 	Copy(data, bytes, h->caplen);
1234 	block = NewCaptureBlock(data, h->caplen);
1235 	LockQueue(e->Queue);
1236 	// Discard arriving packet when queue filled
1237 	if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
1238 		InsertQueue(e->Queue, block);
1239 		e->QueueSize += h->caplen;
1240 	}
1241 	UnlockQueue(e->Queue);
1242 	Cancel(e->Cancel);
1243 	return;
1244 }
1245 
1246 // Relay thread for captured packet (Pcap)
PcapThread(THREAD * thread,void * param)1247 void PcapThread(THREAD *thread, void *param)
1248 {
1249 	ETH *e = (ETH*)param;
1250 	pcap_t *p = e->Pcap;
1251 	int ret;
1252 
1253 	// Notify initialize completed
1254 	NoticeThreadInit(thread);
1255 
1256 	// Return -1:Error -2:Terminated externally
1257 	ret = pcap_loop(p, -1, PcapHandler, (u_char*) e);
1258 	if(ret == -1){
1259 		e->Socket = INVALID_SOCKET;
1260 		pcap_perror(p, "capture");
1261 	}
1262 	return;
1263 }
1264 
1265 
1266 // Open Ethernet adapter (Pcap)
OpenEthPcap(char * name,bool local,bool tapmode,char * tapaddr)1267 ETH *OpenEthPcap(char *name, bool local, bool tapmode, char *tapaddr)
1268 {
1269 	char errbuf[PCAP_ERRBUF_SIZE];
1270 	ETH *e;
1271 	pcap_t *p;
1272 	CANCEL *c;
1273 
1274 	// Validate arguments
1275 	if (name == NULL || tapmode != false)
1276 	{
1277 		return NULL;
1278 	}
1279 
1280 	// Initialize error message buffer
1281 	errbuf[0] = 0;
1282 
1283 	// Open capturing device
1284 	p = pcap_open_live(name, 65535, (local == false), 1, errbuf);
1285 	if(p==NULL)
1286 	{
1287 		return NULL;
1288 	}
1289 
1290 	// Set to non-block mode
1291 	// (In old BSD OSs, 'select(2)' don't block normally for BPF device. To prevent busy loop)
1292 	/*
1293 	if(pcap_setnonblock(p, true, errbuf) == -1)
1294 	{
1295 		Debug("pcap_setnonblock:%s\n",errbuf);
1296 		pcap_close(p);
1297 		return NULL;
1298 	}
1299 	*/
1300 
1301 	e = ZeroMalloc(sizeof(ETH));
1302 	e->Name = CopyStr(name);
1303 	e->Title = CopyStr(name);
1304 	e->Queue = NewQueue();
1305 	e->QueueSize = 0;
1306 	e->Cancel = NewCancel();
1307 	e->IfIndex = -1;
1308 	e->Socket = pcap_get_selectable_fd(p);
1309 	e->Pcap = p;
1310 
1311 	e->CaptureThread = NewThread(PcapThread, e);
1312 	WaitThreadInit(e->CaptureThread);
1313 
1314 	return e;
1315 }
1316 #endif // BRIDGE_PCAP
1317 
1318 #ifdef BRIDGE_BPF
1319 #ifdef BRIDGE_BPF_THREAD
1320 // Relay thread for captured packet (BPF)
BpfThread(THREAD * thread,void * param)1321 void BpfThread(THREAD *thread, void *param)
1322 {
1323 	ETH *e = (ETH*)param;
1324 	int fd = e->Socket;
1325 	int len;
1326 	int rest;	// Rest size in buffer
1327 	UCHAR *next;	// Head of next packet in buffer
1328 	struct CAPTUREBLOCK *block;	// Data to enqueue
1329 	UCHAR *data;
1330 	struct bpf_hdr *hdr;
1331 
1332 	// Allocate the buffer
1333 	UCHAR *buf = Malloc(e->BufSize);
1334 
1335 	// Notify initialize completed
1336 	NoticeThreadInit(thread);
1337 
1338 	while(1){
1339 		// Determining to exit loop
1340 		if(e->Socket == INVALID_SOCKET){
1341 			break;
1342 		}
1343 
1344 		rest = read(fd, buf, e->BufSize);
1345 		if(rest < 0 && errno != EAGAIN){
1346 			// Error
1347 			close(fd);
1348 			e->Socket = INVALID_SOCKET;
1349 			Free(buf);
1350 			Cancel(e->Cancel);
1351 			return;
1352 		}
1353 		next = buf;
1354 		LockQueue(e->Queue);
1355 		while(rest>0){
1356 			// Cut out a packet
1357 			hdr = (struct bpf_hdr*)next;
1358 
1359 			// Discard arriving packet when queue filled
1360 			if(e->QueueSize < BRIDGE_MAX_QUEUE_SIZE){
1361 				data = Malloc(hdr->bh_caplen);
1362 				Copy(data, next+(hdr->bh_hdrlen), hdr->bh_caplen);
1363 				block = NewCaptureBlock(data, hdr->bh_caplen);
1364 				InsertQueue(e->Queue, block);
1365 				e->QueueSize += hdr->bh_caplen;
1366 			}
1367 
1368 			// Find the head of next packet
1369 			rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
1370 			next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
1371 		}
1372 		UnlockQueue(e->Queue);
1373 		Cancel(e->Cancel);
1374 	}
1375 	Free(buf);
1376 	Cancel(e->Cancel);
1377 	return;
1378 }
1379 #endif // BRIDGE_BPF_THREAD
1380 
1381 // Open Ethernet adapter (BPF)
OpenEthBpf(char * name,bool local,bool tapmode,char * tapaddr)1382 ETH *OpenEthBpf(char *name, bool local, bool tapmode, char *tapaddr)
1383 {
1384 	ETH *e;
1385 	CANCEL *c;
1386 	char devname[MAX_SIZE];
1387 	int n = 0;
1388 	int fd;
1389 	int ret;
1390 	UINT bufsize;
1391 	struct ifreq ifr;
1392 	struct timeval to;
1393 
1394 	// Find unused bpf device and open it
1395 	do{
1396 		Format(devname, sizeof(devname), "/dev/bpf%d", n++);
1397 		fd = open (devname, O_RDWR);
1398 		if(fd<0){
1399 			perror("open");
1400 		}
1401 	}while(fd < 0 && errno == EBUSY);
1402 
1403 	// No free bpf device was found
1404 	if(fd < 0){
1405 		Debug("BPF: No minor number are free.\n");
1406 		return NULL;
1407 	}
1408 
1409 	// Enlarge buffer size
1410 	n = 524288; // Somehow(In libpcap, this size is 32768)
1411 	while(true){
1412 		// Specify buffer size
1413 		ioctl(fd, BIOCSBLEN, &n);
1414 
1415 		// Bind to the network device
1416 		StrCpy(ifr.ifr_name, IFNAMSIZ, name);
1417 		ret = ioctl(fd, BIOCSETIF, &ifr);
1418 		if(ret < 0){
1419 			if(ret == ENOBUFS && n>1500){
1420 				// Inappropriate buffer size
1421 				// Retry with half buffer size
1422 				// If buffer size is under 1500 bytes, something goes wrong
1423 				n /= 2;
1424 				continue;
1425 			}
1426 			Debug("bpf: binding network failed.\n");
1427 			close(fd);
1428 			return NULL;
1429 		}else{
1430 			break;
1431 		}
1432 	}
1433 	bufsize = n;
1434 
1435 	// Set to promiscuous mode
1436 	if(local == false){
1437 		if (ioctl(fd, BIOCPROMISC, NULL) < 0){
1438 			printf("bpf: promisc mode failed.\n");
1439 			close(fd);
1440 			return NULL;
1441 		}
1442 	}
1443 
1444 
1445 	// Set to immediate mode (Return immediately when packet arrives)
1446 	n = 1;
1447 	if (ioctl(fd, BIOCIMMEDIATE, &n) < 0){
1448 		Debug("BPF: non-block mode failed.\n");
1449 		close(fd);
1450 		return NULL;
1451 	}
1452 
1453 	// Set receiving self sending packet
1454 	n = 1;
1455 	if (ioctl(fd, BIOCGSEESENT, &n) < 0){
1456 		Debug("BPF: see sent mode failed.\n");
1457 		close(fd);
1458 		return NULL;
1459 	}
1460 
1461 	// Header complete mode (Generate whole header of sending packet)
1462 	n = 1;
1463 	if (ioctl(fd, BIOCSHDRCMPLT, &n) < 0){
1464 		Debug("BPF: Header complete mode failed.\n");
1465 		close(fd);
1466 		return NULL;
1467 	}
1468 
1469 	// Set timeout delay to 1 second
1470 	to.tv_sec = 1;
1471 	to.tv_usec = 0;
1472 	if (ioctl(fd, BIOCSRTIMEOUT, &to) < 0){
1473 		Debug("BPF: Read timeout setting failed.\n");
1474 		close(fd);
1475 		return NULL;
1476 	}
1477 
1478 	e = ZeroMalloc(sizeof(ETH));
1479 	e->Name = CopyStr(name);
1480 	e->Title = CopyStr(name);
1481 	e->IfIndex = -1;
1482 	e->Socket = fd;
1483 	e->BufSize = bufsize;
1484 
1485 #ifdef BRIDGE_BPF_THREAD
1486 	e->Queue = NewQueue();
1487 	e->QueueSize = 0;
1488 	e->Cancel = NewCancel();
1489 
1490 	// Start capture thread
1491 	e->CaptureThread = NewThread(BpfThread, e);
1492 	WaitThreadInit(e->CaptureThread);
1493 
1494 #else // BRIDGE_BPF_THREAD
1495 	c = NewCancel();
1496 	UnixDeletePipe(c->pipe_read, c->pipe_write);
1497 	c->pipe_read = c->pipe_write = -1;
1498 	c->SpecialFlag = true;
1499 	c->pipe_read = fd;
1500 	e->Cancel = c;
1501 	e->Buffer = Malloc(bufsize);
1502 	e->Next = e->Buffer;
1503 	e->Rest = 0;
1504 
1505 	// Set to non-blocking mode
1506 	UnixSetSocketNonBlockingMode(fd, true);
1507 #endif // BRIDGE_BPF_THREAD
1508 
1509 	// Open interface control socket for FreeBSD
1510 	e->SocketBsdIf = socket(AF_LOCAL, SOCK_DGRAM, 0);
1511 
1512 	// Get MTU value
1513 	e->InitialMtu = EthGetMtu(e);
1514 
1515 	return e;
1516 }
1517 #endif // BRIDGE_BPF
1518 
1519 // Open Ethernet adapter
OpenEth(char * name,bool local,bool tapmode,char * tapaddr)1520 ETH *OpenEth(char *name, bool local, bool tapmode, char *tapaddr)
1521 {
1522 	ETH *ret = NULL;
1523 
1524 #if		defined(UNIX_LINUX)
1525 	ret = OpenEthLinux(name, local, tapmode, tapaddr);
1526 #elif	defined(UNIX_SOLARIS)
1527 	ret = OpenEthSolaris(name, local, tapmode, tapaddr);
1528 #elif	defined(BRIDGE_PCAP)
1529 	ret = OpenEthPcap(name, local, tapmode, tapaddr);
1530 #elif	defined(BRIDGE_BPF)
1531 	ret = OpenEthBpf(name, local, tapmode, tapaddr);
1532 #endif
1533 
1534 	return ret;
1535 }
1536 
1537 typedef struct UNIXTHREAD
1538 {
1539 	pthread_t thread;
1540 	bool finished;
1541 } UNIXTHREAD;
1542 
1543 // Close Ethernet adapter
CloseEth(ETH * e)1544 void CloseEth(ETH *e)
1545 {
1546 	// Validate arguments
1547 	if (e == NULL)
1548 	{
1549 		return;
1550 	}
1551 
1552 	if (e->IsRawIpMode)
1553 	{
1554 		CloseEthLinuxIpRaw(e);
1555 
1556 		return;
1557 	}
1558 
1559 	if (e->Tap != NULL)
1560 	{
1561 #ifndef	NO_VLAN
1562 		FreeTap(e->Tap);
1563 #endif	// NO_VLAN
1564 	}
1565 
1566 #ifdef BRIDGE_PCAP
1567 	{
1568 		struct CAPTUREBLOCK *block;
1569 		pcap_breakloop(e->Pcap);
1570 		WaitThread(e->CaptureThread, INFINITE);
1571 		ReleaseThread(e->CaptureThread);
1572 		pcap_close(e->Pcap);
1573 		while (block = GetNext(e->Queue)){
1574 			Free(block->Buf);
1575 			FreeCaptureBlock(block);
1576 		}
1577 		ReleaseQueue(e->Queue);
1578 	}
1579 #endif // BRIDGE_PCAP
1580 
1581 #ifdef BRIDGE_BPF
1582 #ifdef BRIDGE_BPF_THREAD
1583 	{
1584 		struct CAPTUREBLOCK *block;
1585 		int fd = e->Socket;
1586 		e->Socket = INVALID_SOCKET;
1587 		WaitThread(e->CaptureThread, INFINITE);
1588 		ReleaseThread(e->CaptureThread);
1589 		e->Socket = fd; // restore to close after
1590 		while (block = GetNext(e->Queue)){
1591 			Free(block->Buf);
1592 			FreeCaptureBlock(block);
1593 		}
1594 		ReleaseQueue(e->Queue);
1595 	}
1596 #else // BRIDGE_BPF_THREAD
1597 	Free(e->Buffer);
1598 #endif // BRIDGE_BPF_THREAD
1599 #endif // BRIDGE_BPF
1600 
1601 	ReleaseCancel(e->Cancel);
1602 	Free(e->Name);
1603 	Free(e->Title);
1604 
1605 	// Restore MTU value
1606 	EthSetMtu(e, 0);
1607 
1608 	if (e->Socket != INVALID_SOCKET)
1609 	{
1610 #if defined(BRIDGE_BPF) || defined(BRIDGE_PCAP) || defined(UNIX_SOLARIS)
1611 		close(e->Socket);
1612 #else // BRIDGE_PCAP
1613 		closesocket(e->Socket);
1614 #endif // BRIDGE_PCAP
1615 #if defined(BRIDGE_BPF) || defined(UNIX_SOLARIS)
1616 		if (e->SocketBsdIf != INVALID_SOCKET)
1617 		{
1618 			close(e->SocketBsdIf);
1619 		}
1620 #endif	// BRIDGE_BPF || UNIX_SOLARIS
1621 	}
1622 
1623 	Free(e);
1624 }
1625 
1626 // Get cancel object
EthGetCancel(ETH * e)1627 CANCEL *EthGetCancel(ETH *e)
1628 {
1629 	CANCEL *c;
1630 	// Validate arguments
1631 	if (e == NULL)
1632 	{
1633 		return NULL;
1634 	}
1635 
1636 	c = e->Cancel;
1637 	AddRef(c->ref);
1638 
1639 	return c;
1640 }
1641 
1642 // Read a packet
EthGetPacket(ETH * e,void ** data)1643 UINT EthGetPacket(ETH *e, void **data)
1644 {
1645 	UINT ret = 0;
1646 
1647 #if		defined(UNIX_LINUX)
1648 	ret = EthGetPacketLinux(e, data);
1649 #elif	defined(UNIX_SOLARIS)
1650 	ret = EthGetPacketSolaris(e, data);
1651 #elif	defined(BRIDGE_PCAP)
1652 	ret = EthGetPacketPcap(e, data);
1653 #elif	defined(BRIDGE_BPF)
1654 	ret = EthGetPacketBpf(e, data);
1655 #endif
1656 
1657 	return ret;
1658 }
1659 
1660 #ifdef	UNIX_LINUX
1661 
EthGetPacketLinux(ETH * e,void ** data)1662 UINT EthGetPacketLinux(ETH *e, void **data)
1663 {
1664 	int s, ret;
1665 	UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE];
1666 	struct iovec msg_iov;
1667 	struct msghdr msg_header;
1668 	struct cmsghdr *cmsg;
1669 	union
1670 	{
1671 		struct cmsghdr cmsg;
1672 		char buf[CMSG_SPACE(sizeof(struct my_tpacket_auxdata))];
1673 	} cmsg_buf;
1674 	// Validate arguments
1675 	if (e == NULL || data == NULL)
1676 	{
1677 		return INFINITE;
1678 	}
1679 
1680 	if (e->IsRawIpMode)
1681 	{
1682 		return EthGetPacketLinuxIpRaw(e, data);
1683 	}
1684 
1685 	if (e->Tap != NULL)
1686 	{
1687 #ifndef	NO_VLAN
1688 		// tap mode
1689 		void *buf;
1690 		UINT size;
1691 
1692 		if (VLanGetNextPacket(e->Tap, &buf, &size) == false)
1693 		{
1694 			return INFINITE;
1695 		}
1696 
1697 		*data = buf;
1698 		return size;
1699 #else	// NO_VLAN
1700 		return INFINITE;
1701 #endif
1702 	}
1703 
1704 	s = e->Socket;
1705 
1706 	if (s == INVALID_SOCKET)
1707 	{
1708 		return INFINITE;
1709 	}
1710 
1711 	// Read
1712 	msg_iov.iov_base = tmp;
1713 	msg_iov.iov_len = sizeof(tmp);
1714 
1715 	msg_header.msg_name = NULL;
1716 	msg_header.msg_namelen = 0;
1717 	msg_header.msg_iov = &msg_iov;
1718 	msg_header.msg_iovlen = 1;
1719 	if (e->Linux_IsAuxDataSupported)
1720 	{
1721 		memset(&cmsg_buf, 0, sizeof(cmsg_buf));
1722 
1723 		msg_header.msg_control = &cmsg_buf;
1724 		msg_header.msg_controllen = sizeof(cmsg_buf);
1725 	}
1726 	else
1727 	{
1728 		msg_header.msg_control = NULL;
1729 		msg_header.msg_controllen = 0;
1730 	}
1731 	msg_header.msg_flags = 0;
1732 
1733 	ret = recvmsg(s, &msg_header, 0);
1734 	if (ret == 0 || (ret == -1 && errno == EAGAIN))
1735 	{
1736 		// No packet
1737 		*data = NULL;
1738 		return 0;
1739 	}
1740 	else if (ret == -1 || ret > sizeof(tmp))
1741 	{
1742 		// Error
1743 		*data = NULL;
1744 		e->Socket = INVALID_SOCKET;
1745 		return INFINITE;
1746 	}
1747 	else
1748 	{
1749 		bool flag = false;
1750 		USHORT api_vlan_id = 0;
1751 		USHORT api_vlan_tpid = 0;
1752 
1753 		if (e->Linux_IsAuxDataSupported)
1754 		{
1755 			for (cmsg = CMSG_FIRSTHDR(&msg_header); cmsg; cmsg = CMSG_NXTHDR(&msg_header, cmsg))
1756 			{
1757 				struct my_tpacket_auxdata *aux;
1758 				UINT len;
1759 				USHORT vlan_tpid = 0x8100;
1760 				USHORT vlan_id = 0;
1761 
1762 				if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct my_tpacket_auxdata)) ||
1763 					cmsg->cmsg_level != SOL_PACKET ||
1764 					cmsg->cmsg_type != MY_PACKET_AUXDATA)
1765 				{
1766 					continue;
1767 				}
1768 
1769 				aux = (struct my_tpacket_auxdata *)CMSG_DATA(cmsg);
1770 
1771 				if (aux != NULL)
1772 				{
1773 					if (aux->tp_vlan_tci != 0)
1774 					{
1775 						vlan_id = aux->tp_vlan_tci;
1776 					}
1777 				}
1778 
1779 				if (vlan_id != 0)
1780 				{
1781 					api_vlan_id = vlan_id;
1782 					api_vlan_tpid = vlan_tpid;
1783 					break;
1784 				}
1785 			}
1786 
1787 			if (api_vlan_id != 0 && api_vlan_tpid != 0)
1788 			{
1789 				// VLAN ID has been received with PACKET_AUXDATA.
1790 				// Insert the tag.
1791 				USHORT vlan_id_ne = Endian16(api_vlan_id);
1792 				USHORT vlan_tpid_ne = Endian16(api_vlan_tpid);
1793 
1794 				if (ret >= 14)
1795 				{
1796 					if (*((USHORT *)(tmp + 12)) != vlan_tpid_ne)
1797 					{
1798 						*data = MallocFast(ret + 4);
1799 						Copy(*data, tmp, 12);
1800 						Copy(((UCHAR *)*data) + 12, &vlan_tpid_ne, 2);
1801 						Copy(((UCHAR *)*data) + 14, &vlan_id_ne, 2);
1802 						Copy(((UCHAR *)*data) + 16, tmp + 12, ret - 12);
1803 
1804 						flag = true;
1805 
1806 						ret += 4;
1807 					}
1808 				}
1809 			}
1810 		}
1811 
1812 		// Success to read a packet (No VLAN)
1813 		if (flag == false)
1814 		{
1815 			*data = MallocFast(ret);
1816 			Copy(*data, tmp, ret);
1817 		}
1818 		return ret;
1819 	}
1820 
1821 	return 0;
1822 }
1823 #endif	// UNIX_LINUX
1824 
1825 #ifdef	UNIX_SOLARIS
EthGetPacketSolaris(ETH * e,void ** data)1826 UINT EthGetPacketSolaris(ETH *e, void **data)
1827 {
1828 	UCHAR tmp[UNIX_ETH_TMP_BUFFER_SIZE];
1829 	struct strbuf buf;
1830 	int s;
1831 	int flags = 0;
1832 	int ret;
1833 	// Validate arguments
1834 	if (e == NULL || data == NULL)
1835 	{
1836 		return INFINITE;
1837 	}
1838 
1839 	s = e->Socket;
1840 	if (s == INVALID_SOCKET)
1841 	{
1842 		return INFINITE;
1843 	}
1844 
1845 	Zero(&buf, sizeof(buf));
1846 	buf.buf = tmp;
1847 	buf.maxlen = sizeof(tmp);
1848 
1849 	ret = getmsg(s, NULL, &buf, &flags);
1850 
1851 	if (ret < 0 || ret > sizeof(tmp))
1852 	{
1853 		if (errno == EAGAIN)
1854 		{
1855 			// No packet
1856 			*data = NULL;
1857 			return 0;
1858 		}
1859 		// Error
1860 		*data = NULL;
1861 		return INFINITE;
1862 	}
1863 
1864 	ret = buf.len;
1865 
1866 	*data = MallocFast(ret);
1867 	Copy(*data, tmp, ret);
1868 	return ret;
1869 }
1870 #endif	// UNIX_SOLARIS
1871 
1872 #ifdef	BRIDGE_PCAP
EthGetPacketPcap(ETH * e,void ** data)1873 UINT EthGetPacketPcap(ETH *e, void **data)
1874 {
1875 	struct CAPTUREBLOCK *block;
1876 	UINT size;
1877 
1878 	LockQueue(e->Queue);
1879 	block = GetNext(e->Queue);
1880 	if(block != NULL){
1881 		e->QueueSize -= block->Size;
1882 	}
1883 	UnlockQueue(e->Queue);
1884 
1885 	if(block == NULL){
1886 		*data = NULL;
1887 		if(e->Socket == INVALID_SOCKET){
1888 			return INFINITE;
1889 		}
1890 		return 0;
1891 	}
1892 
1893 	*data = block->Buf;
1894 	size = block->Size;
1895 	FreeCaptureBlock(block);
1896 
1897 	return size;
1898 }
1899 #endif // BRIDGE_PCAP
1900 
1901 #ifdef	BRIDGE_BPF
1902 #ifdef BRIDGE_BPF_THREAD
EthGetPacketBpf(ETH * e,void ** data)1903 UINT EthGetPacketBpf(ETH *e, void **data)
1904 {
1905 	struct CAPTUREBLOCK *block;
1906 	UINT size;
1907 
1908 	LockQueue(e->Queue);
1909 	block = GetNext(e->Queue);
1910 	if(block != NULL){
1911 		e->QueueSize -= block->Size;
1912 	}
1913 	UnlockQueue(e->Queue);
1914 
1915 	if(block == NULL){
1916 		*data = NULL;
1917 		if(e->Socket == INVALID_SOCKET){
1918 			return INFINITE;
1919 		}
1920 		return 0;
1921 	}
1922 
1923 	*data = block->Buf;
1924 	size = block->Size;
1925 	FreeCaptureBlock(block);
1926 
1927 	return size;
1928 }
1929 #else // BRIDGE_BPF_THREAD
EthGetPacketBpf(ETH * e,void ** data)1930 UINT EthGetPacketBpf(ETH *e, void **data)
1931 {
1932 	struct bpf_hdr *hdr;
1933 
1934 	if(e->Rest<=0){
1935 		e->Rest = read(e->Socket, e->Buffer, e->BufSize);
1936 		if(e->Rest < 0){
1937 			*data = NULL;
1938 			if(errno != EAGAIN){
1939 				// Error
1940 				return INFINITE;
1941 			}
1942 			// No packet
1943 			return 0;
1944 		}
1945 		e->Next = e->Buffer;
1946 	}
1947 	// Cut out a packet
1948 	hdr = (struct bpf_hdr*)e->Next;
1949 	*data = Malloc(hdr->bh_caplen);
1950 	Copy(*data, e->Next+(hdr->bh_hdrlen), hdr->bh_caplen);
1951 
1952 	// Find the head of next packet
1953 	e->Rest -= BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
1954 	e->Next += BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
1955 
1956 	return hdr->bh_caplen;
1957 }
1958 #endif // BRIDGE_BPF_THREAD
1959 #endif // BRIDGE_BPF
1960 
1961 
1962 // Send multiple packets
EthPutPackets(ETH * e,UINT num,void ** datas,UINT * sizes)1963 void EthPutPackets(ETH *e, UINT num, void **datas, UINT *sizes)
1964 {
1965 	UINT i;
1966 	// Validate arguments
1967 	if (e == NULL || num == 0 || datas == NULL || sizes == NULL)
1968 	{
1969 		return;
1970 	}
1971 
1972 	for (i = 0;i < num;i++)
1973 	{
1974 		EthPutPacket(e, datas[i], sizes[i]);
1975 	}
1976 }
1977 
1978 // Send a packet
EthPutPacket(ETH * e,void * data,UINT size)1979 void EthPutPacket(ETH *e, void *data, UINT size)
1980 {
1981 	int s, ret;
1982 	// Validate arguments
1983 	if (e == NULL || data == NULL)
1984 	{
1985 		return;
1986 	}
1987 	if (e->IsRawIpMode)
1988 	{
1989 		EthPutPacketLinuxIpRaw(e, data, size);
1990 		return;
1991 	}
1992 	if (size < 14 || size > MAX_PACKET_SIZE)
1993 	{
1994 		Free(data);
1995 		return;
1996 	}
1997 
1998 	if (e->Tap != NULL)
1999 	{
2000 #ifndef	NO_VLAN
2001 		// tap mode
2002 		VLanPutPacket(e->Tap, data, size);
2003 #endif	// NO_VLAN
2004 		return;
2005 	}
2006 
2007 	s = e->Socket;
2008 
2009 	if (s == INVALID_SOCKET)
2010 	{
2011 		Free(data);
2012 		return;
2013 	}
2014 
2015 	// Send to device
2016 #ifdef BRIDGE_PCAP
2017 	ret = pcap_inject(e->Pcap, data, size);
2018 	if( ret == -1 ){
2019 #ifdef _DEBUG
2020 		pcap_perror(e->Pcap, "inject");
2021 #endif // _DEBUG
2022 		Debug("EthPutPacket: ret:%d size:%d\n", ret, size);
2023 	}
2024 #else // BRIDGE_PCAP
2025 #ifndef	UNIX_LINUX
2026 	ret = write(s, data, size);
2027 	if (ret<0)
2028 	{
2029 		Debug("EthPutPacket: ret:%d errno:%d  size:%d\n", ret, errno, size);
2030 	}
2031 #else	// UNIX_LINUX
2032 	{
2033 		struct iovec msg_iov;
2034 		struct msghdr msg_header;
2035 
2036 		msg_iov.iov_base = data;
2037 		msg_iov.iov_len = size;
2038 
2039 		msg_header.msg_name = NULL;
2040 		msg_header.msg_namelen = 0;
2041 		msg_header.msg_iov = &msg_iov;
2042 		msg_header.msg_iovlen = 1;
2043 		msg_header.msg_control = NULL;
2044 		msg_header.msg_controllen = 0;
2045 		msg_header.msg_flags = 0;
2046 
2047 		ret = sendmsg(s, &msg_header, 0);
2048 
2049 		if (ret<0)
2050 		{
2051 			Debug("EthPutPacket: ret:%d errno:%d  size:%d\n", ret, errno, size);
2052 		}
2053 	}
2054 #endif	// UNIX_LINUX
2055 #endif //BRIDGE_PCAP
2056 
2057 	Free(data);
2058 }
2059 
2060 
2061 
2062 
2063 // Open ETH by using IP raw packets
OpenEthLinuxIpRaw()2064 ETH *OpenEthLinuxIpRaw()
2065 {
2066 	ETH *e;
2067 
2068 	if (IsRawIpBridgeSupported() == false)
2069 	{
2070 		return NULL;
2071 	}
2072 
2073 	e = ZeroMalloc(sizeof(ETH));
2074 
2075 	e->IsRawIpMode = true;
2076 
2077 	e->RawTcp = NewUDP4(MAKE_SPECIAL_PORT(IPPROTO_TCP), NULL);
2078 	e->RawUdp = NewUDP4(MAKE_SPECIAL_PORT(IPPROTO_UDP), NULL);
2079 	e->RawIcmp = NewUDP4(MAKE_SPECIAL_PORT(IPPROTO_ICMP), NULL);
2080 
2081 	if (e->RawTcp == NULL || e->RawUdp == NULL || e->RawIcmp == NULL)
2082 	{
2083 		ReleaseSock(e->RawTcp);
2084 		ReleaseSock(e->RawUdp);
2085 		ReleaseSock(e->RawIcmp);
2086 
2087 		Free(e);
2088 		return NULL;
2089 	}
2090 
2091 	ClearSockDfBit(e->RawTcp);
2092 	ClearSockDfBit(e->RawUdp);
2093 	ClearSockDfBit(e->RawIcmp);
2094 
2095 	SetRawSockHeaderIncludeOption(e->RawTcp, true);
2096 	SetRawSockHeaderIncludeOption(e->RawUdp, true);
2097 	SetRawSockHeaderIncludeOption(e->RawIcmp, true);
2098 
2099 	e->Name = CopyStr(BRIDGE_SPECIAL_IPRAW_NAME);
2100 	e->Title = CopyStr(BRIDGE_SPECIAL_IPRAW_NAME);
2101 	e->Cancel = NewCancel();
2102 
2103 	UnixDeletePipe(e->Cancel->pipe_read, e->Cancel->pipe_write);
2104 	e->Cancel->pipe_read = e->Cancel->pipe_write = -1;
2105 
2106 	UnixSetSocketNonBlockingMode(e->RawTcp->socket, true);
2107 	UnixSetSocketNonBlockingMode(e->RawUdp->socket, true);
2108 	UnixSetSocketNonBlockingMode(e->RawIcmp->socket, true);
2109 
2110 	e->Cancel->SpecialFlag = true;
2111 	e->Cancel->pipe_read = e->RawTcp->socket;
2112 	e->Cancel->pipe_special_read2 = e->RawUdp->socket;
2113 	e->Cancel->pipe_special_read3 = e->RawIcmp->socket;
2114 
2115 	e->RawIpMyMacAddr[2] = 0x01;
2116 	e->RawIpMyMacAddr[5] = 0x01;
2117 
2118 	SetIP(&e->MyIP, 10, 171, 7, 253);
2119 	SetIP(&e->YourIP, 10, 171, 7, 254);
2120 
2121 	e->RawIpSendQueue = NewQueueFast();
2122 
2123 	e->RawIP_TmpBufferSize = 67000;
2124 	e->RawIP_TmpBuffer = Malloc(e->RawIP_TmpBufferSize);
2125 
2126 	return e;
2127 }
2128 
2129 // Close ETH by using IP raw packets
CloseEthLinuxIpRaw(ETH * e)2130 void CloseEthLinuxIpRaw(ETH *e)
2131 {
2132 	if (e == NULL)
2133 	{
2134 		return;
2135 	}
2136 
2137 	while (true)
2138 	{
2139 		BUF *buf = GetNext(e->RawIpSendQueue);
2140 		if (buf == NULL)
2141 		{
2142 			break;
2143 		}
2144 
2145 		FreeBuf(buf);
2146 	}
2147 	ReleaseQueue(e->RawIpSendQueue);
2148 
2149 	Free(e->Name);
2150 	Free(e->Title);
2151 
2152 	ReleaseSock(e->RawTcp);
2153 	ReleaseSock(e->RawUdp);
2154 	ReleaseSock(e->RawIcmp);
2155 
2156 	ReleaseCancel(e->Cancel);
2157 
2158 	Free(e->RawIP_TmpBuffer);
2159 
2160 	Free(e);
2161 }
2162 
2163 // Receive an IP raw packet
EthGetPacketLinuxIpRaw(ETH * e,void ** data)2164 UINT EthGetPacketLinuxIpRaw(ETH *e, void **data)
2165 {
2166 	UINT r;
2167 	BUF *b;
2168 	// Validate arguments
2169 	if (e == NULL || data == NULL)
2170 	{
2171 		return INFINITE;
2172 	}
2173 	if (e->RawIp_HasError)
2174 	{
2175 		return INFINITE;
2176 	}
2177 
2178 	b = GetNext(e->RawIpSendQueue);
2179 	if (b != NULL)
2180 	{
2181 		UINT size;
2182 
2183 		*data = b->Buf;
2184 		size = b->Size;
2185 
2186 		Free(b);
2187 
2188 		return size;
2189 	}
2190 
2191 	r = EthGetPacketLinuxIpRawForSock(e, data, e->RawTcp, IP_PROTO_TCP);
2192 	if (r == 0)
2193 	{
2194 		r = EthGetPacketLinuxIpRawForSock(e, data, e->RawUdp, IP_PROTO_UDP);
2195 		if (r == 0)
2196 		{
2197 			r = EthGetPacketLinuxIpRawForSock(e, data, e->RawIcmp, IP_PROTO_ICMPV4);
2198 		}
2199 	}
2200 
2201 	if (r == INFINITE)
2202 	{
2203 		e->RawIp_HasError = true;
2204 	}
2205 
2206 	return r;
2207 }
2208 
2209 // Receive an IP raw packet for the specified socket
EthGetPacketLinuxIpRawForSock(ETH * e,void ** data,SOCK * s,UINT proto)2210 UINT EthGetPacketLinuxIpRawForSock(ETH *e, void **data, SOCK *s, UINT proto)
2211 {
2212 	UCHAR *tmp;
2213 	UINT r;
2214 	IP src_addr;
2215 	UINT src_port;
2216 	UINT ret = INFINITE;
2217 	UCHAR *retbuf;
2218 	PKT *p;
2219 	bool ok = false;
2220 	// Validate arguments
2221 	if (e == NULL || data == NULL)
2222 	{
2223 		return INFINITE;
2224 	}
2225 
2226 	tmp = e->RawIP_TmpBuffer;
2227 
2228 LABEL_RETRY:
2229 	*data = NULL;
2230 
2231 	r = RecvFrom(s, &src_addr, &src_port, tmp, e->RawIP_TmpBufferSize);
2232 	if (r == SOCK_LATER)
2233 	{
2234 		return 0;
2235 	}
2236 
2237 	if (r == 0)
2238 	{
2239 		if (s->IgnoreRecvErr)
2240 		{
2241 			return 0;
2242 		}
2243 		else
2244 		{
2245 			return INFINITE;
2246 		}
2247 	}
2248 
2249 	ret = 14 + r;
2250 	retbuf = Malloc(ret);
2251 	*data = retbuf;
2252 
2253 	Copy(retbuf, e->RawIpYourMacAddr, 6);
2254 	Copy(retbuf + 6, e->RawIpMyMacAddr, 6);
2255 	retbuf[12] = 0x08;
2256 	retbuf[13] = 0x00;
2257 	Copy(retbuf + 14, tmp, r);
2258 
2259 	// Mangle packet
2260 	p = ParsePacket(retbuf, ret);
2261 	if (p != NULL)
2262 	{
2263 		if (p->TypeL3 == L3_IPV4)
2264 		{
2265 			IPV4_HEADER *ip;
2266 			IP original_dest_ip;
2267 
2268 			ip = p->L3.IPv4Header;
2269 
2270 			UINTToIP(&original_dest_ip, ip->DstIP);
2271 
2272 			if (IsZeroIP(&e->MyPhysicalIPForce) == false && CmpIpAddr(&e->MyPhysicalIPForce, &original_dest_ip) == 0 ||
2273 				(IsIPMyHost(&original_dest_ip) && IsLocalHostIP(&original_dest_ip) == false && IsHostIPAddress4(&original_dest_ip)))
2274 			{
2275 				if (IsZeroIP(&e->MyPhysicalIPForce) && CmpIpAddr(&e->MyPhysicalIP, &original_dest_ip) != 0)
2276 				{
2277 					// Update MyPhysicalIP
2278 					Copy(&e->MyPhysicalIP, &original_dest_ip, sizeof(IP));
2279 //					Debug("e->MyPhysicalIP = %r\n", &e->MyPhysicalIP);
2280 				}
2281 
2282 				if (IsZeroIP(&e->MyPhysicalIPForce) == false)
2283 				{
2284 					Copy(&e->MyPhysicalIP, &e->MyPhysicalIPForce, sizeof(IP));
2285 				}
2286 
2287 				ip->DstIP = IPToUINT(&e->YourIP);
2288 				ip->Checksum = 0;
2289 				ip->Checksum = IpChecksum(ip, IPV4_GET_HEADER_LEN(ip) * 5);
2290 
2291 				if (p->TypeL4 == L4_TCP)
2292 				{
2293 					TCP_HEADER *tcp = p->L4.TCPHeader;
2294 /*
2295 					if (Endian16(tcp->SrcPort) == 80)
2296 					{
2297 						IP a, b;
2298 						UINTToIP(&a, ip->SrcIP);
2299 						UINTToIP(&b, ip->DstIP);
2300 						Debug("%r %r %u %u\n", &a, &b, Endian16(tcp->SrcPort), Endian16(tcp->DstPort));
2301 					}*/
2302 
2303 					ok = true;
2304 				}
2305 				else if (p->TypeL4 == L4_UDP)
2306 				{
2307 					UDP_HEADER *udp = p->L4.UDPHeader;
2308 
2309 					udp->Checksum = 0;
2310 
2311 					ok = true;
2312 				}
2313 				else if (p->TypeL4 == L4_ICMPV4)
2314 				{
2315 					ICMP_HEADER *icmp = p->L4.ICMPHeader;
2316 
2317 					if (icmp->Type == ICMP_TYPE_DESTINATION_UNREACHABLE || icmp->Type == ICMP_TYPE_TIME_EXCEEDED)
2318 					{
2319 						// Rewrite the Src IP of the IPv4 header of the ICMP response packet
2320 						UINT size = p->PacketSize - ((UCHAR *)icmp - (UCHAR *)p->PacketData);
2321 						UCHAR *data = (UCHAR *)icmp;
2322 						IPV4_HEADER *orig_ipv4 = (IPV4_HEADER *)(((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
2323 						UINT orig_ipv4_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
2324 
2325 						UINT orig_ipv4_header_size = GetIpHeaderSize((UCHAR *)orig_ipv4, orig_ipv4_size);
2326 
2327 						if (orig_ipv4_header_size >= sizeof(IPV4_HEADER) && orig_ipv4_size >= orig_ipv4_header_size)
2328 						{
2329 							if (orig_ipv4->Protocol == IP_PROTO_ICMPV4)
2330 							{
2331 								// Search the inner ICMP header
2332 								UINT inner_icmp_size = orig_ipv4_size - orig_ipv4_header_size;
2333 
2334 								if (inner_icmp_size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
2335 								{
2336 									ICMP_HEADER *inner_icmp = (ICMP_HEADER *)(((UCHAR *)data) +
2337 										sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO) + orig_ipv4_header_size);
2338 
2339 									if (inner_icmp->Type == ICMP_TYPE_ECHO_REQUEST)
2340 									{
2341 										ICMP_ECHO *inner_echo = (ICMP_ECHO *)(((UCHAR *)inner_icmp) + sizeof(ICMP_HEADER));
2342 
2343 										inner_icmp->Checksum = 0;
2344 										orig_ipv4->SrcIP = IPToUINT(&e->YourIP);
2345 										orig_ipv4->Checksum = 0;
2346 										orig_ipv4->Checksum = IpChecksum(orig_ipv4, orig_ipv4_header_size);
2347 
2348 										// Rewrite the outer ICMP header
2349 										if (true)
2350 										{
2351 											UCHAR *payload;
2352 											UINT payload_size;
2353 											ICMP_ECHO *echo;
2354 
2355 											// Echo Response
2356 											echo = (ICMP_ECHO *)(((UCHAR *)data) + sizeof(ICMP_HEADER));
2357 
2358 											if (size >= (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO)))
2359 											{
2360 												payload = ((UCHAR *)data) + sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO);
2361 												payload_size = size - (sizeof(ICMP_HEADER) + sizeof(ICMP_ECHO));
2362 
2363 												// Rewrite the header
2364 												icmp->Checksum = 0;
2365 												icmp->Checksum = IpChecksum(icmp, size);
2366 											}
2367 										}
2368 									}
2369 								}
2370 							}
2371 						}
2372 					}
2373 
2374 					icmp->Checksum = 0;
2375 					icmp->Checksum = IpChecksum(icmp, p->PayloadSize);
2376 
2377 					ok = true;
2378 				}
2379 				else if (p->TypeL4 == L4_FRAGMENT)
2380 				{
2381 					ok = true;
2382 				}
2383 			}
2384 		}
2385 
2386 		FreePacket(p);
2387 	}
2388 
2389 	if (ok == false)
2390 	{
2391 		Free(*data);
2392 		*data = NULL;
2393 
2394 		goto LABEL_RETRY;
2395 	}
2396 
2397 	return ret;
2398 }
2399 
2400 // Send internal IP packet (insert into the send queue)
EthSendIpPacketInnerIpRaw(ETH * e,void * data,UINT size,USHORT protocol)2401 void EthSendIpPacketInnerIpRaw(ETH *e, void *data, UINT size, USHORT protocol)
2402 {
2403 	BUF *b;
2404 	if (e == NULL || data == NULL || size == 0)
2405 	{
2406 		return;
2407 	}
2408 
2409 	if (e->RawIpSendQueue->num_item >= 1024)
2410 	{
2411 		return;
2412 	}
2413 
2414 	b = NewBuf();
2415 	WriteBuf(b, e->RawIpYourMacAddr, 6);
2416 	WriteBuf(b, e->RawIpMyMacAddr, 6);
2417 	WriteBufShort(b, protocol);
2418 	WriteBuf(b, data, size);
2419 	SeekBufToBegin(b);
2420 
2421 	InsertQueue(e->RawIpSendQueue, b);
2422 }
2423 
2424 // Process the packet internal if necessary
EthProcessIpPacketInnerIpRaw(ETH * e,PKT * p)2425 bool EthProcessIpPacketInnerIpRaw(ETH *e, PKT *p)
2426 {
2427 	bool ret = false;
2428 	if (e == NULL || p == NULL)
2429 	{
2430 		return false;
2431 	}
2432 
2433 	if (p->TypeL3 == L3_ARPV4)
2434 	{
2435 		// ARP processing
2436 		ARPV4_HEADER *arp = p->L3.ARPv4Header;
2437 
2438 		if (Endian16(arp->HardwareType) == ARP_HARDWARE_TYPE_ETHERNET &&
2439 			Endian16(arp->ProtocolType) == MAC_PROTO_IPV4 &&
2440 			arp->HardwareSize == 6 && arp->ProtocolType == 4)
2441 		{
2442 			if (IPToUINT(&e->MyIP) == arp->TargetIP)
2443 			{
2444 				if (Endian16(arp->Operation) == ARP_OPERATION_REQUEST)
2445 				{
2446 					ARPV4_HEADER r;
2447 
2448 					Zero(&r, sizeof(r));
2449 					r.HardwareType = Endian16(ARP_HARDWARE_TYPE_ETHERNET);
2450 					r.ProtocolType = Endian16(MAC_PROTO_IPV4);
2451 					r.HardwareSize = 6;
2452 					r.ProtocolSize = 4;
2453 					r.Operation = Endian16(ARP_OPERATION_RESPONSE);
2454 					Copy(r.SrcAddress, e->RawIpMyMacAddr, 6);
2455 					Copy(r.TargetAddress, arp->SrcAddress, 6);
2456 					r.SrcIP = IPToUINT(&e->MyIP);
2457 					r.TargetIP = arp->SrcIP;
2458 
2459 					EthSendIpPacketInnerIpRaw(e, &r, sizeof(ARPV4_HEADER), MAC_PROTO_ARPV4);
2460 				}
2461 			}
2462 		}
2463 	}
2464 	else if (p->TypeL3 == L3_IPV4 && p->TypeL4 == L4_UDP && p->TypeL7 == L7_DHCPV4)
2465 	{
2466 		// DHCP processing
2467 		DHCPV4_HEADER *dhcp;
2468 		UCHAR *data;
2469 		UINT size;
2470 		UINT dhcp_header_size;
2471 		UINT dhcp_data_offset;
2472 		UINT tran_id;
2473 		UINT magic_cookie = Endian32(DHCP_MAGIC_COOKIE);
2474 		bool ok;
2475 		DHCP_OPTION_LIST *opt;
2476 
2477 		dhcp = p->L7.DHCPv4Header;
2478 		tran_id = Endian32(dhcp->TransactionId);
2479 
2480 		// Get the DHCP data and size
2481 		dhcp_header_size = sizeof(DHCPV4_HEADER);
2482 		dhcp_data_offset = (UINT)(((UCHAR *)p->L7.DHCPv4Header) - ((UCHAR *)p->MacHeader) + dhcp_header_size);
2483 		data = ((UCHAR *)dhcp) + dhcp_header_size;
2484 		size = p->PacketSize - dhcp_data_offset;
2485 		if (dhcp_header_size < 5)
2486 		{
2487 			// Data size is invalid
2488 			return false;
2489 		}
2490 
2491 		// Search for Magic Cookie
2492 		ok = false;
2493 		while (size >= 5)
2494 		{
2495 			if (Cmp(data, &magic_cookie, sizeof(magic_cookie)) == 0)
2496 			{
2497 				// Found
2498 				data += 4;
2499 				size -= 4;
2500 				ok = true;
2501 				break;
2502 			}
2503 			data++;
2504 			size--;
2505 		}
2506 
2507 		if (ok == false)
2508 		{
2509 			// The packet is invalid
2510 			return false;
2511 		}
2512 
2513 		// Parse DHCP options list
2514 		opt = ParseDhcpOptionList(data, size);
2515 		if (opt == NULL)
2516 		{
2517 			// The packet is invalid
2518 			return false;
2519 		}
2520 
2521 		if (dhcp->OpCode == 1 && (opt->Opcode == DHCP_DISCOVER || opt->Opcode == DHCP_REQUEST || opt->Opcode == DHCP_INFORM))
2522 		{
2523 			// Operate as the server
2524 			UINT ip = IPToUINT(&e->YourIP);
2525 			if (ip != 0 || opt->Opcode == DHCP_INFORM)
2526 			{
2527 				// Respond if there is providable IP address
2528 				DHCP_OPTION_LIST ret;
2529 				LIST *o;
2530 				UINT hw_type;
2531 				UINT hw_addr_size;
2532 				UINT new_ip = ip;
2533 				IP default_dns;
2534 
2535 				Zero(&default_dns, sizeof(default_dns));
2536 
2537 				Zero(&ret, sizeof(ret));
2538 
2539 				ret.Opcode = (opt->Opcode == DHCP_DISCOVER ? DHCP_OFFER : DHCP_ACK);
2540 				ret.ServerAddress = IPToUINT(&e->MyIP);
2541 				ret.LeaseTime = 3600;
2542 				if (opt->Opcode == DHCP_INFORM)
2543 				{
2544 					ret.LeaseTime = 0;
2545 				}
2546 
2547 				ret.SubnetMask = SetIP32(255, 255, 255, 252);
2548 
2549 				if (UnixGetDefaultDns(&default_dns) && IsZeroIp(&default_dns) == false)
2550 				{
2551 					ret.DnsServer = IPToUINT(&default_dns);
2552 					ret.DnsServer2 = SetIP32(8, 8, 8, 8);
2553 				}
2554 				else
2555 				{
2556 					ret.DnsServer = SetIP32(8, 8, 8, 8);
2557 					ret.DnsServer2 = SetIP32(8, 8, 4, 4);
2558 				}
2559 
2560 				ret.Gateway = IPToUINT(&e->MyIP);
2561 
2562 				if (opt->Opcode != DHCP_INFORM)
2563 				{
2564 					char client_mac[MAX_SIZE];
2565 					char client_ip[64];
2566 					IP ips;
2567 					BinToStr(client_mac, sizeof(client_mac), p->MacAddressSrc, 6);
2568 					UINTToIP(&ips, ip);
2569 					IPToStr(client_ip, sizeof(client_ip), &ips);
2570 					Debug("IP_RAW: DHCP %s : %s given %s\n",
2571 						ret.Opcode == DHCP_OFFER ? "DHCP_OFFER" : "DHCP_ACK",
2572 						client_mac, client_ip);
2573 				}
2574 
2575 				// Build a DHCP option
2576 				o = BuildDhcpOption(&ret);
2577 				if (o != NULL)
2578 				{
2579 					BUF *b = BuildDhcpOptionsBuf(o);
2580 					if (b != NULL)
2581 					{
2582 						UINT dest_ip = p->L3.IPv4Header->SrcIP;
2583 						UINT blank_size = 128 + 64;
2584 						UINT dhcp_packet_size;
2585 						UINT magic = Endian32(DHCP_MAGIC_COOKIE);
2586 						DHCPV4_HEADER *dhcp;
2587 						void *magic_cookie_addr;
2588 						void *buffer_addr;
2589 
2590 						if (dest_ip == 0)
2591 						{
2592 							dest_ip = 0xffffffff;
2593 						}
2594 
2595 						// Calculate the DHCP packet size
2596 						dhcp_packet_size = blank_size + sizeof(DHCPV4_HEADER) + sizeof(magic) + b->Size;
2597 
2598 						if (dhcp_packet_size < DHCP_MIN_SIZE)
2599 						{
2600 							// Padding
2601 							dhcp_packet_size = DHCP_MIN_SIZE;
2602 						}
2603 
2604 						// Create a header
2605 						dhcp = ZeroMalloc(dhcp_packet_size);
2606 
2607 						dhcp->OpCode = 2;
2608 						dhcp->HardwareType = hw_type;
2609 						dhcp->HardwareAddressSize = hw_addr_size;
2610 						dhcp->Hops = 0;
2611 						dhcp->TransactionId = Endian32(tran_id);
2612 						dhcp->Seconds = 0;
2613 						dhcp->Flags = 0;
2614 						dhcp->YourIP = new_ip;
2615 						dhcp->ServerIP = IPToUINT(&e->MyIP);
2616 						Copy(dhcp->ClientMacAddress, p->MacAddressSrc, 6);
2617 
2618 						// Calculate the address
2619 						magic_cookie_addr = (((UCHAR *)dhcp) + sizeof(DHCPV4_HEADER) + blank_size);
2620 						buffer_addr = ((UCHAR *)magic_cookie_addr) + sizeof(magic);
2621 
2622 						// Magic Cookie
2623 						Copy(magic_cookie_addr, &magic, sizeof(magic));
2624 
2625 						// Buffer
2626 						Copy(buffer_addr, b->Buf, b->Size);
2627 
2628 						if (true)
2629 						{
2630 							UCHAR *data = ZeroMalloc(sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + dhcp_packet_size);
2631 							IPV4_HEADER *ipv4 = (IPV4_HEADER *)(data);
2632 							UDP_HEADER *udp = (UDP_HEADER *)(data + sizeof(IPV4_HEADER));
2633 
2634 							Copy(data + sizeof(IPV4_HEADER) + sizeof(UDP_HEADER), dhcp, dhcp_packet_size);
2635 
2636 							IPV4_SET_VERSION(ipv4, 4);
2637 							IPV4_SET_HEADER_LEN(ipv4, 5);
2638 							ipv4->TotalLength = Endian16(sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + dhcp_packet_size);
2639 							ipv4->TimeToLive = 63;
2640 							ipv4->Protocol = IP_PROTO_UDP;
2641 							ipv4->SrcIP = IPToUINT(&e->MyIP);
2642 							ipv4->DstIP = dest_ip;
2643 							ipv4->Checksum = IpChecksum(ipv4, sizeof(IPV4_HEADER));
2644 
2645 							udp->SrcPort = Endian16(NAT_DHCP_SERVER_PORT);
2646 							udp->DstPort = Endian16(NAT_DHCP_CLIENT_PORT);
2647 							udp->PacketLength = Endian16(sizeof(UDP_HEADER) + dhcp_packet_size);
2648 							udp->Checksum = CalcChecksumForIPv4(ipv4->SrcIP, ipv4->DstIP, IP_PROTO_UDP,
2649 								dhcp, dhcp_packet_size, 0);
2650 							if (udp->Checksum == 0)
2651 							{
2652 								udp->Checksum = 0xffff;
2653 							}
2654 
2655 							EthSendIpPacketInnerIpRaw(e, data, sizeof(IPV4_HEADER) + sizeof(UDP_HEADER) + dhcp_packet_size, MAC_PROTO_IPV4);
2656 
2657 							Free(data);
2658 						}
2659 
2660 						// Release the memory
2661 						Free(dhcp);
2662 						FreeBuf(b);
2663 					}
2664 					FreeDhcpOptions(o);
2665 				}
2666 			}
2667 		}
2668 
2669 		Free(opt);
2670 	}
2671 
2672 	return ret;
2673 }
2674 
2675 // Send an IP raw packet
EthPutPacketLinuxIpRaw(ETH * e,void * data,UINT size)2676 void EthPutPacketLinuxIpRaw(ETH *e, void *data, UINT size)
2677 {
2678 	PKT *p;
2679 	// Validate arguments
2680 	if (e == NULL || data == NULL)
2681 	{
2682 		return;
2683 	}
2684 	if (size < 14 || size > MAX_PACKET_SIZE || e->RawIp_HasError)
2685 	{
2686 		Free(data);
2687 		return;
2688 	}
2689 
2690 	p = ParsePacket(data, size);
2691 
2692 	if (p != NULL && (p->BroadcastPacket || Cmp(p->MacAddressDest, e->RawIpMyMacAddr, 6) == 0))
2693 	{
2694 		if (IsValidUnicastMacAddress(p->MacAddressSrc))
2695 		{
2696 			Copy(e->RawIpYourMacAddr, p->MacAddressSrc, 6);
2697 		}
2698 	}
2699 
2700 	if (IsZero(e->RawIpYourMacAddr, 6) || IsValidUnicastMacAddress(p->MacAddressSrc) == false ||
2701 		(p != NULL && p->BroadcastPacket == false && Cmp(p->MacAddressDest, e->RawIpMyMacAddr, 6) != 0))
2702 	{
2703 		Free(data);
2704 		FreePacket(p);
2705 		return;
2706 	}
2707 
2708 	if (p != NULL)
2709 	{
2710 		SOCK *s = NULL;
2711 
2712 		if (p->TypeL3 == L3_IPV4)
2713 		{
2714 			if (p->TypeL4 == L4_TCP)
2715 			{
2716 				if (IsZeroIP(&e->MyPhysicalIP) == false)
2717 				{
2718 					s = e->RawTcp;
2719 				}
2720 			}
2721 			else if (p->TypeL4 == L4_UDP)
2722 			{
2723 				if (EthProcessIpPacketInnerIpRaw(e, p) == false)
2724 				{
2725 					s = e->RawUdp;
2726 				}
2727 			}
2728 			else if (p->TypeL4 == L4_ICMPV4)
2729 			{
2730 				if (IsZeroIP(&e->MyPhysicalIP) == false)
2731 				{
2732 					s = e->RawIcmp;
2733 				}
2734 			}
2735 			else if (p->TypeL4 == L4_FRAGMENT)
2736 			{
2737 				if (IsZeroIP(&e->MyPhysicalIP) == false)
2738 				{
2739 					s = e->RawIcmp;
2740 				}
2741 			}
2742 		}
2743 		else if (p->TypeL3 == L3_ARPV4)
2744 		{
2745 			EthProcessIpPacketInnerIpRaw(e, p);
2746 		}
2747 
2748 		if (s != NULL && p->L3.IPv4Header->DstIP != 0xffffffff && p->BroadcastPacket == false &&
2749 			p->L3.IPv4Header->SrcIP == IPToUINT(&e->YourIP))
2750 		{
2751 			UCHAR *send_data = p->IPv4PayloadData;
2752 			UCHAR *head = p->PacketData;
2753 			UINT remove_header_size = (UINT)(send_data - head);
2754 
2755 			if (p->PacketSize > remove_header_size)
2756 			{
2757 				IP dest;
2758 				UINT send_data_size = p->PacketSize - remove_header_size;
2759 
2760 				// checksum
2761 				if (p->TypeL4 == L4_UDP)
2762 				{
2763 					p->L4.UDPHeader->Checksum = 0;
2764 				}
2765 				else if (p->TypeL4 == L4_TCP)
2766 				{
2767 					p->L4.TCPHeader->Checksum = 0;
2768 					p->L4.TCPHeader->Checksum = CalcChecksumForIPv4(IPToUINT(&e->MyPhysicalIP),
2769 						p->L3.IPv4Header->DstIP, IP_PROTO_TCP,
2770 						p->L4.TCPHeader, p->IPv4PayloadSize, 0);
2771 				}
2772 
2773 				UINTToIP(&dest, p->L3.IPv4Header->DstIP);
2774 
2775 				if (s->RawIP_HeaderIncludeFlag == false)
2776 				{
2777 					SendTo(s, &dest, 0, send_data, send_data_size);
2778 				}
2779 				else
2780 				{
2781 					IPV4_HEADER *ip = p->L3.IPv4Header;
2782 
2783 					ip->SrcIP = IPToUINT(&e->MyPhysicalIP);
2784 					ip->Checksum = 0;
2785 					ip->Checksum = IpChecksum(ip, IPV4_GET_HEADER_LEN(ip) * 4);
2786 
2787 					SendTo(s, &dest, 0, ip, ((UCHAR *)p->PacketData - (UCHAR *)ip) + p->PacketSize);
2788 				}
2789 			}
2790 		}
2791 
2792 		FreePacket(p);
2793 	}
2794 
2795 	Free(data);
2796 }
2797 
2798 
2799 #endif	// BRIDGE_C
2800 
2801 
2802