Skip to content

Commit db16f59

Browse files
committed
Added different usage options
1 parent 80ca4ad commit db16f59

File tree

2 files changed

+174
-25
lines changed

2 files changed

+174
-25
lines changed

README.md

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# ptr - Find hostname of IP addresses
1+
# IP PTR Lookup Script
22

3-
-
3+
This is a simple Go script that performs PTR (reverse DNS) lookups for IP addresses. It can handle single IP addresses, IP addresses from a file, or IP addresses provided via stdin.
44

55
## Installation
66

@@ -11,3 +11,37 @@ go install github.com/topscoder/ptr@latest
1111
```
1212

1313
This will install the ptr script as an executable in your Go bin directory.
14+
15+
## Usage
16+
17+
Run the script with different options:
18+
19+
* To look up a single IP address:
20+
21+
```shell
22+
ptr 8.8.8.8
23+
```
24+
25+
* To process IP addresses from a file (one IP address per line):
26+
27+
```shell
28+
ptr ips.txt
29+
```
30+
31+
* To provide IP addresses via stdin (press Ctrl + D to signal the end of input):
32+
33+
```shell
34+
cat ips.txt | ptr -
35+
```
36+
37+
Enjoy the PTR lookup results!
38+
39+
## License
40+
41+
This project is licensed under the MIT License.
42+
43+
Feel free to fork the repository, make improvements, and submit pull requests!
44+
45+
## Acknowledgements
46+
47+
This script was inspired by the need for a simple tool to perform PTR lookups for multiple IP addresses quickly.

ptr.go

Lines changed: 138 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,151 @@
11
package main
22

33
import (
4-
"fmt"
5-
"net"
6-
"os"
7-
"strings"
4+
"bufio"
5+
"fmt"
6+
"net"
7+
"os"
8+
"strings"
9+
"sync"
810
)
911

1012
func main() {
11-
args := os.Args[1:]
13+
args := os.Args[1:]
1214

13-
if len(args) != 1 {
14-
fmt.Println("Usage: ptr <ip_address>")
15-
return
16-
}
15+
if len(args) < 1 {
16+
printUsage()
17+
return
18+
}
1719

18-
ip := args[0]
20+
arg := args[0]
1921

20-
ptrDomainName, err := net.LookupAddr(ip)
21-
if err != nil {
22-
fmt.Println("No PTR record found for", ip)
23-
return
24-
}
22+
if isFile(arg) {
23+
processFile(arg)
24+
} else if arg == "-" {
25+
processStdin()
26+
} else {
27+
processSingleIP(arg)
28+
}
29+
}
30+
31+
func printUsage() {
32+
fmt.Println("Usage:")
33+
fmt.Println(" ptr <ip_address_or_input_file>")
34+
fmt.Println()
35+
fmt.Println("Options:")
36+
fmt.Println(" <ip_address_or_input_file> Provide an IP address, an input file with one IP address per line, or use '-' to read IP addresses from stdin.")
37+
}
38+
39+
func isFile(path string) bool {
40+
info, err := os.Stat(path)
41+
if err != nil {
42+
return false
43+
}
44+
return !info.IsDir()
45+
}
46+
47+
func processFile(filePath string) {
48+
file, err := os.Open(filePath)
49+
if err != nil {
50+
fmt.Println("Error opening file:", err)
51+
return
52+
}
53+
defer file.Close()
54+
55+
scanner := bufio.NewScanner(file)
56+
var wg sync.WaitGroup
57+
ipChannel := make(chan string)
58+
59+
// Start worker goroutines
60+
for i := 0; i < 10; i++ { // Adjust the number of goroutines as needed
61+
wg.Add(1)
62+
go processIPs(ipChannel, &wg)
63+
}
64+
65+
// Send IPs to worker goroutines through channel
66+
for scanner.Scan() {
67+
ip := strings.TrimSpace(scanner.Text())
68+
if ip != "" {
69+
ipChannel <- ip
70+
}
71+
}
72+
close(ipChannel)
73+
74+
wg.Wait()
75+
76+
if err := scanner.Err(); err != nil {
77+
fmt.Println("Error reading file:", err)
78+
}
79+
}
80+
81+
func processStdin() {
82+
scanner := bufio.NewScanner(os.Stdin)
83+
var wg sync.WaitGroup
84+
ipChannel := make(chan string)
85+
86+
// Start worker goroutines
87+
for i := 0; i < 10; i++ { // Adjust the number of goroutines as needed
88+
wg.Add(1)
89+
go processIPs(ipChannel, &wg)
90+
}
91+
92+
// Send IPs to worker goroutines through channel
93+
for scanner.Scan() {
94+
ip := strings.TrimSpace(scanner.Text())
95+
if ip != "" {
96+
ipChannel <- ip
97+
}
98+
}
99+
close(ipChannel)
100+
101+
wg.Wait()
102+
103+
if err := scanner.Err(); err != nil {
104+
fmt.Println("Error reading input:", err)
105+
}
106+
}
107+
108+
func processSingleIP(ip string) {
109+
var wg sync.WaitGroup
110+
ipChannel := make(chan string)
111+
112+
// Start worker goroutines
113+
for i := 0; i < 10; i++ { // Adjust the number of goroutines as needed
114+
wg.Add(1)
115+
go processIPs(ipChannel, &wg)
116+
}
117+
118+
// Send the single IP to worker goroutines through channel
119+
ipChannel <- ip
120+
close(ipChannel)
121+
122+
wg.Wait()
123+
}
124+
125+
func processIPs(ipChannel <-chan string, wg *sync.WaitGroup) {
126+
defer wg.Done()
127+
128+
for ip := range ipChannel {
129+
ptrDomainNames, err := net.LookupAddr(ip)
130+
if err != nil {
131+
fmt.Printf("%s\t%v\n", ip, err)
132+
continue
133+
}
134+
135+
var cleanedDomainNames []string
136+
137+
for _, ptrDomainName := range ptrDomainNames {
138+
// Remove the brackets from the PTR domain name.
139+
ptrDomainName = strings.Trim(ptrDomainName, "[")
25140

26-
// Remove the brackets from the PTR domain name.
27-
ptrDomainName = strings.Trim(ptrDomainName, "[")
28-
ptrDomainName = strings.Trim(ptrDomainName, "]")
141+
// Remove the last character if it is a dot.
142+
if ptrDomainName[len(ptrDomainName)-1] == '.' {
143+
ptrDomainName = ptrDomainName[:len(ptrDomainName)-1]
144+
}
29145

30-
// Remove the last character if it is a dot.
31-
if ptrDomainName[len(ptrDomainName)-1] == '.' {
32-
ptrDomainName = ptrDomainName[:len(ptrDomainName)-1]
33-
}
146+
cleanedDomainNames = append(cleanedDomainNames, ptrDomainName)
147+
}
34148

35-
fmt.Println(ptrDomainName)
149+
fmt.Printf("%s\t%s\n", ip, strings.Join(cleanedDomainNames, "\n"))
150+
}
36151
}

0 commit comments

Comments
 (0)