mirror of https://github.com/perkeep/perkeep.git
Add camli/netutil library for ident-like lookups.
This commit is contained in:
parent
467ae0a9e0
commit
5634523637
1
build.pl
1
build.pl
|
@ -409,6 +409,7 @@ TARGET: lib/go/camli/magic
|
|||
TARGET: lib/go/camli/misc/httprange
|
||||
TARGET: lib/go/camli/misc/amazon/s3
|
||||
TARGET: lib/go/camli/mysqlindexer
|
||||
TARGET: lib/go/camli/netutil
|
||||
TARGET: lib/go/camli/schema
|
||||
TARGET: lib/go/camli/search
|
||||
TARGET: lib/go/camli/test
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
Copyright 2011 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ = log.Printf
|
||||
|
||||
// TODO: Linux-specific right now.
|
||||
// Returns os.ENOENT on not found.
|
||||
func ConnUserid(conn net.Conn) (uid int, err os.Error) {
|
||||
return AddrPairUserid(conn.LocalAddr().String(), conn.RemoteAddr().String())
|
||||
}
|
||||
|
||||
func splitIPPort(param, value string) (ip net.IP, port int, reterr os.Error) {
|
||||
addrs, ports, err := net.SplitHostPort(value)
|
||||
if err != nil {
|
||||
reterr = fmt.Errorf("netutil: AddrPairUserid invalid %s value: %v", err)
|
||||
return
|
||||
}
|
||||
ip = net.ParseIP(addrs)
|
||||
if ip == nil {
|
||||
reterr = fmt.Errorf("netutil: invalid %s IP %q", param, addrs)
|
||||
return
|
||||
}
|
||||
port, err = strconv.Atoi(ports)
|
||||
if err != nil || port <= 0 || port > 65535 {
|
||||
reterr = fmt.Errorf("netutil: invalid port %q", ports)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AddrPairUserid returns the local userid who owns the TCP connection
|
||||
// given by the local and remote ip:port (lipport and ripport,
|
||||
// respectively). Returns os.ENOENT for the error if the TCP connection
|
||||
// isn't found.
|
||||
func AddrPairUserid(lipport, ripport string) (uid int, err os.Error) {
|
||||
lip, lport, err := splitIPPort("lipport", lipport)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
rip, rport, err := splitIPPort("ripport", ripport)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
localv4 := (lip.To4() != nil)
|
||||
remotev4 := (rip.To4() != nil)
|
||||
if localv4 != remotev4 {
|
||||
return -1, fmt.Errorf("netutil: address pairs of different families; localv4=%v, remotev4=%v",
|
||||
localv4, remotev4)
|
||||
}
|
||||
|
||||
file := "/proc/net/tcp"
|
||||
if !localv4 {
|
||||
file = "/proc/net/tcp6"
|
||||
}
|
||||
f, err := os.Open(file, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("Error opening %s: %v", file, err)
|
||||
}
|
||||
defer f.Close()
|
||||
return uidFromReader(lip, lport, rip, rport, f)
|
||||
}
|
||||
|
||||
func reverseIPBytes(b []byte) []byte {
|
||||
rb := make([]byte, len(b))
|
||||
for i, v := range b {
|
||||
rb[len(b) - i - 1] = v
|
||||
}
|
||||
return rb
|
||||
}
|
||||
|
||||
func uidFromReader(lip net.IP, lport int, rip net.IP, rport int, r io.Reader) (uid int, err os.Error) {
|
||||
buf := bufio.NewReader(r)
|
||||
|
||||
localHex := ""
|
||||
remoteHex := ""
|
||||
if lip.To4() != nil {
|
||||
// In the kernel, the port is run through ntohs(), and
|
||||
// the inet_request_socket in
|
||||
// include/net/inet_socket.h says the "loc_addr" and
|
||||
// "rmt_addr" fields are __be32, but get_openreq4's
|
||||
// printf of them is raw, without byte order
|
||||
// converstion.
|
||||
localHex = fmt.Sprintf("%08X:%04X", reverseIPBytes([]byte(lip.To4())), lport)
|
||||
remoteHex = fmt.Sprintf("%08X:%04X", reverseIPBytes([]byte(rip.To4())), rport)
|
||||
} else {
|
||||
localHex = fmt.Sprintf("%032X:%04X", []byte(lip.To16()), lport)
|
||||
remoteHex = fmt.Sprintf("%032X:%04X", []byte(rip.To16()), rport)
|
||||
}
|
||||
|
||||
for {
|
||||
line, err := buf.ReadString('\n')
|
||||
if err != nil {
|
||||
return -1, os.ENOENT
|
||||
}
|
||||
parts := strings.Fields(strings.TrimSpace(line))
|
||||
if len(parts) < 8 {
|
||||
continue
|
||||
}
|
||||
// log.Printf("parts[1] = %q; localHex = %q", parts[1], localHex)
|
||||
if parts[1] == localHex && parts[2] == remoteHex {
|
||||
uid, _ = strconv.Atoi(parts[7])
|
||||
return
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright 2011 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package netutil
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var _ = log.Printf
|
||||
|
||||
// TODO: test IPv6. probably not working.
|
||||
|
||||
func TestIdent4(t *testing.T) {
|
||||
lip := net.ParseIP("67.218.110.129")
|
||||
lport := 43436
|
||||
rip := net.ParseIP("207.7.148.195")
|
||||
rport := 80
|
||||
|
||||
// 816EDA43:A9AC C39407CF:0050
|
||||
// 43436 80
|
||||
uid, err := uidFromReader(lip, lport, rip, rport, ioutil.NopCloser(strings.NewReader(tcpstat4)))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if e, g := 61652, uid; e != g {
|
||||
t.Errorf("expected uid %d, got %d", e, g)
|
||||
}
|
||||
}
|
||||
|
||||
var tcpstat4 = ` sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||||
0: 0100007F:C204 00000000:0000 0A 00000000:00000000 00:00000000 00000000 61652 0 8722922 1 ffff880036b36180 300 0 0 2 -1
|
||||
1: 0100007F:0CEA 00000000:0000 0A 00000000:00000000 00:00000000 00000000 120 0 5714729 1 ffff880036b35480 300 0 0 2 -1
|
||||
2: 0100007F:2BCB 00000000:0000 0A 00000000:00000000 00:00000000 00000000 65534 0 7381 1 ffff880136370000 300 0 0 2 -1
|
||||
3: 0100007F:13AD 00000000:0000 0A 00000000:00000000 00:00000000 00000000 61652 0 4846349 1 ffff880123eb5480 300 0 0 2 -1
|
||||
4: 00000000:0050 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8307 1 ffff880123eb0d00 300 0 0 2 -1
|
||||
5: 00000000:0071 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8558503 1 ffff88001a242080 300 0 0 2 -1 6: 0100007F:7533 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8686 1 ffff880136371380 300 0 0 2 -1
|
||||
7: 017AA8C0:0035 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 6015 1 ffff880123eb0680 300 0 0 2 -1
|
||||
8: 0100007F:0277 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 8705543 1 ffff88001a242d80 300 0 0 2 -1
|
||||
9: 816EDA43:D4DC 35E07D4A:01BB 01 00000000:00000000 02:00000E25 00000000 61652 0 8720744 2 ffff88001a243a80 346 4 24 3 2
|
||||
10: 0100007F:C204 0100007F:D981 01 00000000:00000000 00:00000000 00000000 61652 0 8722934 1 ffff88006712a700 21 4 30 5 -1
|
||||
11: 816EDA43:A9AC C39407CF:0050 01 00000000:00000000 00:00000000 00000000 61652 0 8754873 1 ffff88006712db00 27 0 0 3 -1
|
||||
12: 816EDA43:AFEF 51357D4A:01BB 01 00000000:00000000 02:00000685 00000000 61652 0 8752937 2 ffff880136375480 87 4 2 4 -1
|
||||
13: 0100007F:D981 0100007F:C204 01 00000000:00000000 00:00000000 00000000 61652 0 8722933 1 ffff880036b30d00 21 4 0 3 -1
|
||||
`
|
Loading…
Reference in New Issue