package linux import ( "errors" "net" "regexp" "strconv" "strings" ) var ( ipv4RegExp = regexp.MustCompile("^[0-9a-fA-F]{8}:[0-9a-fA-F]{4}$") // Regex for NetIPv4Decoder ipv6RegExp = regexp.MustCompile("^[0-9a-fA-F]{32}:[0-9a-fA-F]{4}$") // Regex for NetIPv6Decoder ) type NetIPDecoder func(string) (string, error) // Either NetIPv4Decoder or NetIPv6Decoder type NetSocket struct { LocalAddress string `json:"local_address"` RemoteAddress string `json:"remote_address"` Status uint8 `json:"st"` TxQueue uint64 `json:"tx_queue"` RxQueue uint64 `json:"rx_queue"` Uid uint32 `json:"uid"` Inode uint64 `json:"inode"` SocketReferenceCount uint64 `json:"ref"` } func parseNetSocket(f []string, ip NetIPDecoder) (*NetSocket, error) { if len(f) < 11 { return nil, errors.New("Cannot parse net socket line: " + strings.Join(f, " ")) } if strings.Index(f[4], ":") == -1 { return nil, errors.New("Cannot parse tx/rx queues: " + f[4]) } q := strings.Split(f[4], ":") socket := &NetSocket{} var s uint64 // socket.Status var u uint64 // socket.Uid var err error // parse error if socket.LocalAddress, err = ip(f[1]); err != nil { return nil, err } if socket.RemoteAddress, err = ip(f[2]); err != nil { return nil, err } if s, err = strconv.ParseUint(f[3], 16, 8); err != nil { return nil, err } if socket.TxQueue, err = strconv.ParseUint(q[0], 16, 64); err != nil { return nil, err } if socket.RxQueue, err = strconv.ParseUint(q[1], 16, 64); err != nil { return nil, err } if u, err = strconv.ParseUint(f[7], 10, 32); err != nil { return nil, err } if socket.Inode, err = strconv.ParseUint(f[9], 10, 64); err != nil { return nil, err } if socket.SocketReferenceCount, err = strconv.ParseUint(f[10], 10, 64); err != nil { return nil, err } socket.Status = uint8(s) socket.Uid = uint32(u) return socket, nil } // Decode an IPv4 address with port from a given hex string // NOTE: This function match NetIPDecoder type func NetIPv4Decoder(s string) (string, error) { if !ipv4RegExp.MatchString(s) { return "", errors.New("Cannot decode ipv4 address: " + s) } i := strings.Split(s, ":") b := make([]byte, 4) for j := 0; j < 4; j++ { x := j * 2 y := x + 2 z := 3 - j // Extract 2 characters from hex string, 4 times. // // s: "0100007F" -> [ // h: "01", h: "00", h: "00", h: "7F", // ] h := i[0][x:y] // Reverse byte order n, _ := strconv.ParseUint(h, 16, 8) b[z] = byte(n) } h := net.IP(b).String() n, _ := strconv.ParseUint(i[1], 16, 64) p := strconv.FormatUint(n, 10) // ipv4:port v := h + ":" + p return v, nil } // Decode an IPv6 address with port from a given hex string // NOTE: This function match NetIPDecoder type func NetIPv6Decoder(s string) (string, error) { if !ipv6RegExp.MatchString(s) { return "", errors.New("Cannot decode ipv6 address: " + s) } i := strings.Split(s, ":") b := make([]byte, 16) for j := 0; j < 4; j++ { x := j * 8 y := x + 8 // Extract 8 characters from hex string, 4 times. // // s: "350E012A900F122E85EDEAADA64DAAD1" -> [ // h: "350E012A", h: "900F122E", // h: "85EDEAAD", h: "A64DAAD1", // ] h := i[0][x:y] for k := 0; k < 4; k++ { // Reverse byte order // "350E012A" -> [ 0x2A, 0x01, 0x0E, 0x35 ] z := (j * 4) + k g := 8 - (k * 2) f := g - 2 n, _ := strconv.ParseUint(h[f:g], 16, 8) b[z] = byte(n) } } h := net.IP(b).String() n, _ := strconv.ParseUint(i[1], 16, 64) p := strconv.FormatUint(n, 10) // ipv6:port v := h + ":" + p return v, nil }