private UnixStream OpenSocket(uint?mtu) { sockaddr_ll sa = new sockaddr_ll(); sa.sll_family = AF_PACKET; sa.sll_protocol = (ushort)IPAddress.HostToNetworkOrder((short)Protocol); sa.sll_ifindex = if_nametoindex(Interface); if (sa.sll_ifindex == 0) { throw new ArgumentException("The interface \"" + Interface + "\" is not valid."); } int fd = -1, ret = -1; try { fd = socket(AF_PACKET, SOCK_RAW, sa.sll_protocol); UnixMarshal.ThrowExceptionForLastErrorIf(fd); ret = bind(fd, ref sa, Marshal.SizeOf(sa)); UnixMarshal.ThrowExceptionForLastErrorIf(ret); ifreq ifr = new ifreq(Interface); if (orig_mtu == 0) { ret = ioctl(fd, SIOCGIFMTU, ref ifr); UnixMarshal.ThrowExceptionForLastErrorIf(ret); orig_mtu = ifr.ifru_mtu; } if (mtu != null) { ifr.ifru_mtu = mtu.Value; ret = ioctl(fd, SIOCSIFMTU, ref ifr); UnixMarshal.ThrowExceptionForLastErrorIf(ret); } ret = ioctl(fd, SIOCGIFMTU, ref ifr); UnixMarshal.ThrowExceptionForLastErrorIf(ret); if (mtu != null && ifr.ifru_mtu != mtu.Value) { throw new PeachException("MTU change did not take effect."); } _mtu = ifr.ifru_mtu; if (ifr.ifru_mtu > (MaxMTU - EthernetHeaderSize)) { _bufferSize = (int)MaxMTU; } else { _bufferSize = (int)(ifr.ifru_mtu + EthernetHeaderSize); } var stream = new UnixStream(fd); fd = -1; return(stream); } catch (InvalidOperationException ex) { if (ex.InnerException != null) { var inner = ex.InnerException as UnixIOException; if (inner != null && inner.ErrorCode == Errno.EPERM) { throw new PeachException("Access denied when opening the raw ethernet publisher. Ensure the user has the appropriate permissions.", ex); } } throw; } finally { if (fd != -1) { Syscall.close(fd); } } }
private static extern int bind(int fd, ref sockaddr_ll addr, int addrlen);