func (c *CIDRs) UnmarshalBinary(b []byte) error { if len(b) < 1 { return fmt.Errorf("compare: missing type byte") } if b[0] != byte(TypeCIDRs) { return fmt.Errorf("compare: expected type %d, got %d", TypeCIDRs, b[0]) } b = b[1:] *c = make(CIDRs, 0, len(b)/ipv4CIDRLen) for len(b) > 0 { var n net.IPNet if b[0]&(1<<7) == 0 { // check top bit of ones byte, if 0, IPv4, if 1, IPv6 if len(b) < ipv4CIDRLen { return fmt.Errorf("compare: unexpected end of buffer decoding IPv4 CIDR") } n.Mask = net.CIDRMask(int(b[0]), ipv4Len*8) n.IP = net.IPv4(b[1], b[2], b[3], b[4]) b = b[5:] } else { if len(b) < ipv6CIDRLen { return fmt.Errorf("compare: unexpected end of buffer decoding IPv6 CIDR") } n.Mask = net.CIDRMask(int(b[0]&^(1<<7)), ipv6Len*8) n.IP = make([]byte, ipv6Len) copy(n.IP, b[1:]) b = b[ipv6CIDRLen:] } *c = append(*c, n) } return nil }
func decodeInet(vr *ValueReader) net.IPNet { var zero net.IPNet if vr.Len() == -1 { vr.Fatal(ProtocolError("Cannot decode null into net.IPNet")) return zero } if vr.Type().FormatCode != BinaryFormatCode { vr.Fatal(ProtocolError(fmt.Sprintf("Unknown field description format code: %v", vr.Type().FormatCode))) return zero } pgType := vr.Type() if vr.Len() != 8 && vr.Len() != 20 { vr.Fatal(ProtocolError(fmt.Sprintf("Received an invalid size for a %s: %d", pgType.Name, vr.Len()))) return zero } if pgType.DataType != InetOid && pgType.DataType != CidrOid { vr.Fatal(ProtocolError(fmt.Sprintf("Cannot decode oid %v into %s", pgType.DataType, pgType.Name))) return zero } vr.ReadByte() // ignore family bits := vr.ReadByte() vr.ReadByte() // ignore is_cidr addressLength := vr.ReadByte() var ipnet net.IPNet ipnet.IP = vr.ReadBytes(int32(addressLength)) ipnet.Mask = net.CIDRMask(int(bits), int(addressLength)*8) return ipnet }
// hasIP6Connected parses the list of remote addresses in /proc/net/{tcp,udp}6 or in // /proc/<pid>/net/{tcp,udp}6 and returns addresses that are contained within // the ipnet submitted. It always uses CIDR inclusion, even when only // searching for a single IP (but assuming a /128 bitmask). // Remote addresses exposed in /proc are in hexadecimal notation, and converted into byte slices // to use in ipnet.Contains() func hasIP6Connected(ip net.IP, ipnet *net.IPNet) (found bool, elements []element, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("hasIP6Connected(): %v", e) } }() lns, err := procIP6Entries() if err != nil { panic(err) } // if the ipnet is nil, assume that its a full 128bits mask if ipnet == nil { ipnet = new(net.IPNet) ipnet.IP = ip ipnet.Mask = net.CIDRMask(net.IPv6len*8, net.IPv6len*8) } for _, ipent := range lns { fields := strings.Fields(ipent.line) if len(fields) < 4 { panic("/proc doesn't respect the expected format") } remote := strings.Split(fields[2], ":") if len(remote) != 2 { panic("remote isn't in the form <ip>:<port>") } remoteIP := hexToIP6(remote[0]) if remoteIP == nil { panic("failed to convert remote IP") } // if we've got a match, store the element if ipnet.Contains(remoteIP) { var el element el.RemoteAddr = remoteIP.String() remotePort, err := strconv.ParseUint(remote[1], 16, 16) if err != nil { panic("failed to convert remote port") } el.RemotePort = float64(remotePort) local := strings.Split(fields[1], ":") if len(local) != 2 { panic("local isn't in the form <ip>:<port>") } localAddr := hexToIP6(local[0]) if localAddr == nil { panic("failed to convert local ip") } el.LocalAddr = localAddr.String() localPort, err := strconv.ParseUint(local[1], 16, 16) if err != nil { panic("failed to convert local port") } el.LocalPort = float64(localPort) el.Namespace = ipent.nsIdentifier elements = append(elements, el) found = true } stats.Examined++ } return }
// Updates the network mask with the real on from the cloud config. func updateIPNet(ipnet *net.IPNet) error { // Retrieve the configuration ids projectId, err := fetchProjectId() if err != nil { return err } networkId, err := fetchNetworkId() if err != nil { return err } // Create a service account connection to the GCE API client, err := serviceaccount.NewClient(&serviceaccount.Options{}) if err != nil { return err } gce, err := compute.New(client) if err != nil { return err } // Fetch the network configurations and update the netmask network, err := gce.Networks.Get(projectId, networkId).Do() if err != nil { return err } _, ipn, err := net.ParseCIDR(network.IPv4Range) if err != nil { return err } ipnet.Mask = ipn.Mask return nil }
func parseIPPattern(ipp string) (*net.IPNet, error) { ipnet := net.IPNet{} ipnet.IP = net.ParseIP(ipp) if ipnet.IP != nil { if ipnet.IP.To4() != nil { ipnet.Mask = net.CIDRMask(32, 32) } else { ipnet.Mask = net.CIDRMask(128, 128) } return &ipnet, nil } else { _, ipnet, err := net.ParseCIDR(ipp) if err != nil { return nil, err } return ipnet, nil } }
// SpanningCIDR computes network covers given IP addresses func SpanningCIDR(first, last net.IP) *net.IPNet { _, bits := last.DefaultMask().Size() var network net.IPNet for ones := bits; !network.Contains(first); ones-- { network.Mask = net.CIDRMask(ones, bits) network.IP = last.Mask(network.Mask) } return &network }
// ParseIPandMask parses a CIDR format address (e.g. 1.1.1.1/8) func ParseIPandMask(s string) (net.IPNet, error) { var i net.IPNet ip, ipnet, err := net.ParseCIDR(s) if err != nil { return i, err } i.IP = ip i.Mask = ipnet.Mask return i, nil }
func decodeInetArray(vr *ValueReader) []net.IPNet { if vr.Len() == -1 { return nil } if vr.Type().DataType != InetArrayOid && vr.Type().DataType != CidrArrayOid { vr.Fatal(ProtocolError(fmt.Sprintf("Cannot decode oid %v into []net.IP", vr.Type().DataType))) return nil } if vr.Type().FormatCode != BinaryFormatCode { vr.Fatal(ProtocolError(fmt.Sprintf("Unknown field description format code: %v", vr.Type().FormatCode))) return nil } numElems, err := decode1dArrayHeader(vr) if err != nil { vr.Fatal(err) return nil } a := make([]net.IPNet, int(numElems)) for i := 0; i < len(a); i++ { elSize := vr.ReadInt32() if elSize == -1 { vr.Fatal(ProtocolError("Cannot decode null element")) return nil } vr.ReadByte() // ignore family bits := vr.ReadByte() vr.ReadByte() // ignore is_cidr addressLength := vr.ReadByte() var ipnet net.IPNet ipnet.IP = vr.ReadBytes(int32(addressLength)) ipnet.Mask = net.CIDRMask(int(bits), int(addressLength)*8) a[i] = ipnet } return a }
func hasSeenIP6(ip net.IP, ipnet *net.IPNet) (found bool, elements []element, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("hasSeenIP6(): %v", e) } }() lns, err := procArpEntries() if err != nil { panic(err) } // if the ipnet is nil, assume that its a full 128bits mask if ipnet == nil { ipnet = new(net.IPNet) ipnet.IP = ip ipnet.Mask = net.CIDRMask(net.IPv6len*8, net.IPv6len*8) } for _, arpent := range lns { fields := strings.Fields(arpent.line) if len(fields) < 4 { continue } remoteIP := net.ParseIP(fields[0]) if remoteIP == nil { panic("failed to convert remote IP") } // if we've got a match, store the element if ipnet.Contains(remoteIP) { var el element el.RemoteAddr = remoteIP.String() el.RemoteMACAddr = fields[3] el.Namespace = arpent.nsIdentifier elements = append(elements, el) found = true } stats.Examined++ } return }
func encodeInet(w *WriteBuf, value interface{}) error { var ipnet net.IPNet switch value := value.(type) { case net.IPNet: ipnet = value case net.IP: ipnet.IP = value bitCount := len(value) * 8 ipnet.Mask = net.CIDRMask(bitCount, bitCount) default: return fmt.Errorf("Expected net.IPNet, received %T %v", value, value) } var size int32 var family byte switch len(ipnet.IP) { case net.IPv4len: size = 8 family = w.conn.pgsql_af_inet case net.IPv6len: size = 20 family = w.conn.pgsql_af_inet6 default: return fmt.Errorf("Unexpected IP length: %v", len(ipnet.IP)) } w.WriteInt32(size) w.WriteByte(family) ones, _ := ipnet.Mask.Size() w.WriteByte(byte(ones)) w.WriteByte(0) // is_cidr is ignored on server w.WriteByte(byte(len(ipnet.IP))) w.WriteBytes(ipnet.IP) return nil }
// hasIP6Connected parse the list of remote addresses in /proc/net/{tcp,udp}6 and returns addresses // that are contained within the ipnet submitted. It always uses CIDR inclusion, even when only // searching for a single IP (but assuming a /128 bitmask). // Remote addresses exposed in /proc are in hexadecimal notation, and converted into byte slices // to use in ipnet.Contains() func hasIP6Connected(ip net.IP, ipnet *net.IPNet) (found bool, elements []element, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("hasIP6Connected(): %v", e) } }() var connfiles = [...]string{`/proc/net/tcp6`, `/proc/net/udp6`} // if the ipnet is nil, assume that its a full 128bits mask if ipnet == nil { ipnet = new(net.IPNet) ipnet.IP = ip ipnet.Mask = net.CIDRMask(net.IPv6len*8, net.IPv6len*8) } for _, f := range connfiles { fd, err := os.Open(f) defer fd.Close() if err != nil { panic(err) } scanner := bufio.NewScanner(fd) scanner.Scan() // skip the header for scanner.Scan() { if err := scanner.Err(); err != nil { panic(err) } fields := strings.Fields(scanner.Text()) if len(fields) < 4 { panic("/proc doesn't respect the expected format") } remote := strings.Split(fields[2], ":") if len(remote) != 2 { panic("remote isn't in the form <ip>:<port>") } remoteIP := hexToIP6(remote[0]) if remoteIP == nil { panic("failed to convert remote IP") } // if we've got a match, store the element if ipnet.Contains(remoteIP) { var el element el.RemoteAddr = remoteIP.String() remotePort, err := strconv.ParseUint(remote[1], 16, 16) if err != nil { panic("failed to convert remote port") } el.RemotePort = float64(remotePort) local := strings.Split(fields[1], ":") if len(local) != 2 { panic("local isn't in the form <ip>:<port>") } localAddr := hexToIP6(local[0]) if localAddr == nil { panic("failed to convert local ip") } el.LocalAddr = localAddr.String() localPort, err := strconv.ParseUint(local[1], 16, 16) if err != nil { panic("failed to convert local port") } el.LocalPort = float64(localPort) elements = append(elements, el) found = true } stats.Examined++ } } return }
// Creates a new bootstrapper, configuring to listen on the given interface for // for incoming requests and scan the same interface for other peers. The magic // is used to filter multiple Iris networks in the same physical network, while // the overlay is the TCP listener port of the DHT. func New(ipnet *net.IPNet, magic []byte, owner *big.Int, endpoint int) (*Bootstrapper, chan *Event, error) { logger := log15.New("subsys", "bootstrap", "ipnet", ipnet) gobber := gobber.New() gobber.Init(new(Message)) // Do some environment dependent IP black magic if detectGoogleComputeEngine() { // Google Compute Engine issues /32 addresses, find real subnet logger.Info("detected GCE, retrieving real netmask") old := ipnet.String() if err := updateIPNet(ipnet); err != nil { logger.Error("failed to retrieve netmask, defaulting", "error", err) ipnet.Mask = ipnet.IP.DefaultMask() } logger.Info("network subnet mask replaced", "old", old, "new", ipnet) logger = log15.New("subsys", "bootstrap", "ipnet", ipnet) } b := &Bootstrapper{ ipnet: ipnet, magic: magic, beats: make(chan *Event, config.BootBeatsBuffer), phase: uint32(0), gob: gobber, request: newBootstrapRequest(magic, owner, endpoint, gobber), response: newBootstrapResponse(magic, owner, endpoint, gobber), // Seeding algorithms and address sinks scanSeed: newScanSeeder(ipnet, logger), probeSeed: newProbeSeeder(ipnet, logger), coreOSSeed: newCoreOSSeeder(ipnet, logger), scanSink: make(chan *net.IPAddr, config.BootSeedSinkBuffer), probeSink: make(chan *net.IPAddr, config.BootSeedSinkBuffer), coreOSSink: make(chan *net.IPAddr, config.BootSeedSinkBuffer), // Maintenance fields quit: make(chan chan error), log: logger, } // Open the server socket var err error for _, port := range config.BootPorts { b.addr, err = net.ResolveUDPAddr("udp", net.JoinHostPort(ipnet.IP.String(), strconv.Itoa(port))) if err != nil { return nil, nil, err } b.sock, err = net.ListenUDP("udp", b.addr) if err != nil { continue } else { b.addr.Port = b.sock.LocalAddr().(*net.UDPAddr).Port b.mask = &ipnet.Mask break } } if err != nil { return nil, nil, fmt.Errorf("no available ports") } // Return the ready-to-boot bootstrapper return b, b.beats, nil }
func (p *Parser) parseMX(t *Token) (bool, SPFResult) { result, _ := matchingResult(t.Qualifier) domain := p.setDomain(t) var host string var v4Network *net.IPMask var v6Network *net.IPMask var ok bool ok, host, v4Network, v6Network = splitToHostNetwork(domain) host = NormalizeHost(host) // return Permerror if there was syntax error if !ok { return true, Permerror } var err error // TODO(zaccone): Ensure returned errors are correct. query := new(dns.Msg) query.SetQuestion(host, dns.TypeMX) c := new(dns.Client) response, _, err := c.Exchange(query, Nameserver) if err != nil { fmt.Println(err) return false, None } if response != nil && response.Rcode != dns.RcodeSuccess { if response.Rcode != dns.RcodeNameError { return true, Temperror } else { fmt.Println(err) return false, None } } mxs := make([]string, 0, len(response.Answer)) for _, answer := range response.Answer { if mx, ok := answer.(*dns.MX); ok { mxs = append(mxs, mx.Mx) } } var wg sync.WaitGroup pipe := make(chan bool) wg.Add(len(mxs)) go func() { wg.Wait() close(pipe) }() for _, mmx := range mxs { go func(mx string, v4Network, v6Network *net.IPMask) { defer wg.Done() mx = NormalizeHost(mx) v4Ipnet := net.IPNet{} v4Ipnet.Mask = *v4Network v6Ipnet := net.IPNet{} v6Ipnet.Mask = *v6Network ips4 := make([]net.IP, 0, 1) ips6 := make([]net.IP, 0, 1) var queries [2]dns.Msg queries[0].SetQuestion(mx, dns.TypeA) queries[1].SetQuestion(mx, dns.TypeAAAA) for _, query := range queries { c := new(dns.Client) response, _, err := c.Exchange(&query, Nameserver) if err != nil { pipe <- false return } if response != nil && response.Rcode != dns.RcodeSuccess { pipe <- false return } for _, answer := range response.Answer { if ans, ok := answer.(*dns.A); ok { ips4 = append(ips4, ans.A) } else if ans, ok := answer.(*dns.AAAA); ok { ips6 = append(ips6, ans.AAAA) } } } var contains bool for _, address := range ips4 { v4Ipnet.IP = address contains = v4Ipnet.Contains(p.IP) pipe <- contains } for _, address := range ips6 { v6Ipnet.IP = address contains = v6Ipnet.Contains(p.IP) pipe <- contains } }(mmx, v4Network, v6Network) } verdict := false for subverdict := range pipe { verdict = verdict || subverdict } return verdict, result }
func (p *Parser) parseA(t *Token) (bool, SPFResult) { result, _ := matchingResult(t.Qualifier) domain := p.setDomain(t) var host string var v4Network *net.IPMask var v6Network *net.IPMask var ok bool ips4 := make([]net.IP, 0, 1) ips6 := make([]net.IP, 0, 1) ok, host, v4Network, v6Network = splitToHostNetwork(domain) host = NormalizeHost(host) // return Permerror if there was syntax error if !ok { return true, Permerror } var queries [2]dns.Msg queries[0].SetQuestion(host, dns.TypeA) queries[1].SetQuestion(host, dns.TypeAAAA) for _, query := range queries { c := new(dns.Client) r, _, err := c.Exchange(&query, Nameserver) if err != nil { fmt.Println(err) return true, Temperror } if r != nil && r.Rcode != dns.RcodeSuccess { if r.Rcode != dns.RcodeNameError { fmt.Println(r) return true, Temperror } else { return false, None } } else { for _, answer := range r.Answer { if ans, ok := answer.(*dns.A); ok { ips4 = append(ips4, ans.A) } else if ans, ok := answer.(*dns.AAAA); ok { ips6 = append(ips6, ans.AAAA) } } } } v4Ipnet := net.IPNet{} v4Ipnet.Mask = *v4Network v6Ipnet := net.IPNet{} v6Ipnet.Mask = *v6Network for _, address := range ips4 { v4Ipnet.IP = address if v4Ipnet.Contains(p.IP) { return true, result } } for _, address := range ips6 { v6Ipnet.IP = address if v6Ipnet.Contains(p.IP) { return true, result } } return false, result }
func HasIPConnected(val string) (found bool, elements []element, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("HasIPConnected(): %v", e) } }() found = false var ipnet *net.IPNet // if val contains a /, treat it as a cidr if strings.IndexAny(val, "/") > 0 { _, ipnet, err = net.ParseCIDR(val) if err != nil { panic(err) } // otherwise assume it's a single address (v4 /32 or v6 /128) } else { ip := net.ParseIP(val) if ip == nil { panic("Invalid IP") } ipnet = new(net.IPNet) ipnet.IP = ip ipnet.Mask = net.CIDRMask(len(ip), len(ip)) } var fam string if len(ipnet.IP) == 4 { fam = "inet" } else { fam = "inet6" } out, err := exec.Command("netstat", "-naW", "-f", fam).Output() if err != nil { panic(err) } buf := bytes.NewReader(out) reader := bufio.NewReader(buf) for { lineBytes, _, err := reader.ReadLine() if err != nil { break } line := fmt.Sprintf("%s", lineBytes) fields := strings.Fields(line) if len(fields) <= 4 { continue } localIP, localPort, err := parseEndpointString(fields[3]) if err != nil { break } remoteIP, remotePort, err := parseEndpointString(fields[4]) if err != nil { break } if remoteIP != nil && ipnet.Contains(remoteIP) { var el element el.RemoteAddr = remoteIP.String() if remotePort != -1 { el.RemotePort = float64(remotePort) } if localIP != nil { el.LocalAddr = localIP.String() } if localPort != -1 { el.LocalPort = float64(localPort) } elements = append(elements, el) found = true } stats.Examined++ } return }
// NgrepUnmarshal parses the ngrep output read from r and stores the result // in the l. func NgrepUnmarshal(r io.Reader, l *Log) error { type state uint8 const ( stHead state = iota stT stRaw ) var ( t *Transmission buf = bufio.NewReader(r) st = stHead ) for { b, err := buf.ReadBytes('\n') if len(b) == 0 { if err == io.EOF { return nil } if err != nil { return err } } switch st { case stRaw: if len(b) == 1 && b[0] == '\n' { st = stT continue } if b[len(b)-2] == '.' { b[len(b)-2] = '\r' } t.Raw = append(t.Raw, b...) case stT: if m := tre.FindStringSubmatch(string(b)); m != nil { l.T = append(l.T, Transmission{}) t = &l.T[len(l.T)-1] if t.Src, err = parseAddr(m[1]); err != nil { return err } if t.Dst, err = parseAddr(m[2]); err != nil { return err } st = stRaw } case stHead: if len(b) == 1 && b[0] == '\n' { st = stT continue } line := string(b) if m := headre[0].FindStringSubmatch(line); m != nil { var network net.IPNet if network.IP = net.ParseIP(m[1]); network.IP == nil { return errors.New("ill-formed IP " + m[1]) } mask := net.ParseIP(m[2]) if mask == nil { return errors.New("ill-formed IP mask " + m[2]) } network.Mask = iptomask(mask) l.Networks = []*net.IPNet{&network} } else if m := headre[1].FindStringSubmatch(line); m != nil { l.Filter = m[1] } } } }