// Open Ethernet device (Linux) ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr) { ETH *e; struct ifreq ifr; struct sockaddr_ll addr; int s; int index; CANCEL *c; // Validate arguments if (name == NULL) { return NULL; } if (tapmode) { #ifndef NO_VLAN // In tap mode VLAN *v = NewTap(name, tapaddr); if (v == NULL) { return NULL; } e = ZeroMalloc(sizeof(ETH)); e->Name = CopyStr(name); e->Title = CopyStr(name); e->Cancel = VLanGetCancel(v); e->IfIndex = 0; e->Socket = INVALID_SOCKET; e->Tap = v; return e; #else // NO_VLAN return NULL; #endif // NO_VLAN } s = UnixEthOpenRawSocket(); if (s == INVALID_SOCKET) { return NULL; } Zero(&ifr, sizeof(ifr)); StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name); if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { closesocket(s); return NULL; } index = ifr.ifr_ifindex; Zero(&addr, sizeof(addr)); addr.sll_family = PF_PACKET; addr.sll_protocol = htons(ETH_P_ALL); addr.sll_ifindex = index; if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { closesocket(s); return NULL; } if (local == false) { // Enable promiscious mode Zero(&ifr, sizeof(ifr)); StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name); if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { // Failed closesocket(s); return NULL; } ifr.ifr_flags |= IFF_PROMISC; if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) { // Failed closesocket(s); return NULL; } } e = ZeroMalloc(sizeof(ETH)); e->Name = CopyStr(name); e->Title = CopyStr(name); e->IfIndex = index; e->Socket = s; c = NewCancel(); UnixDeletePipe(c->pipe_read, c->pipe_write); c->pipe_read = c->pipe_write = -1; UnixSetSocketNonBlockingMode(s, true); c->SpecialFlag = true; c->pipe_read = s; e->Cancel = c; // Get MTU e->InitialMtu = EthGetMtu(e); if (tapmode == false) { // Disable hardware offloading UnixDisableInterfaceOffload(name); } return e; }
// Open Ethernet device (Linux) ETH *OpenEthLinux(char *name, bool local, bool tapmode, char *tapaddr) { ETH *e; struct ifreq ifr; struct sockaddr_ll addr; int s; int index; bool aux_ok = false; CANCEL *c; // Validate arguments if (name == NULL) { return NULL; } if (tapmode) { #ifndef NO_VLAN // In tap mode VLAN *v = NewTap(name, tapaddr); if (v == NULL) { return NULL; } e = ZeroMalloc(sizeof(ETH)); e->Name = CopyStr(name); e->Title = CopyStr(name); e->Cancel = VLanGetCancel(v); e->IfIndex = 0; e->Socket = INVALID_SOCKET; e->Tap = v; return e; #else // NO_VLAN return NULL; #endif // NO_VLAN } s = UnixEthOpenRawSocket(); if (s == INVALID_SOCKET) { return NULL; } Zero(&ifr, sizeof(ifr)); StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name); if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) { closesocket(s); return NULL; } index = ifr.ifr_ifindex; Zero(&addr, sizeof(addr)); addr.sll_family = PF_PACKET; addr.sll_protocol = htons(ETH_P_ALL); addr.sll_ifindex = index; if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { closesocket(s); return NULL; } if (local == false) { // Enable promiscious mode Zero(&ifr, sizeof(ifr)); StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name); if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) { // Failed closesocket(s); return NULL; } ifr.ifr_flags |= IFF_PROMISC; if (ioctl(s, SIOCSIFFLAGS, &ifr) < 0) { // Failed closesocket(s); return NULL; } } if (true) { int val = 1; int ss_ret = setsockopt(s, SOL_PACKET, MY_PACKET_AUXDATA, &val, sizeof(val)); if (ss_ret < 0) { Debug("eth(%s): setsockopt: PACKET_AUXDATA failed.\n", name); } else { Debug("eth(%s): setsockopt: PACKET_AUXDATA ok.\n", name); aux_ok = true; } } e = ZeroMalloc(sizeof(ETH)); e->Name = CopyStr(name); e->Title = CopyStr(name); e->IfIndex = index; e->Socket = s; e->Linux_IsAuxDataSupported = aux_ok; c = NewCancel(); UnixDeletePipe(c->pipe_read, c->pipe_write); c->pipe_read = c->pipe_write = -1; UnixSetSocketNonBlockingMode(s, true); c->SpecialFlag = true; c->pipe_read = s; e->Cancel = c; // Get MTU e->InitialMtu = EthGetMtu(e); if (tapmode == false) { if (GetGlobalServerFlag(GSF_LOCALBRIDGE_NO_DISABLE_OFFLOAD) == false) { bool b = false; LockList(eth_offload_list); { if (IsInListStr(eth_offload_list, name) == false) { b = true; Add(eth_offload_list, CopyStr(name)); } } UnlockList(eth_offload_list); if (b) { // Disable hardware offloading UnixDisableInterfaceOffload(name); } } } return e; }