7272 // ErrTimeout error
7373 ErrTimeout = errors .New ("timeout" )
7474
75+ // ErrNoUsableInterface no usable interface found
76+ ErrNoUsableInterface = errors .New ("no usable interface found" )
77+
7578 verboseLog = log .New (ioutil .Discard , "" , 0 )
7679 timeout = time .Duration (500 * time .Millisecond )
7780)
@@ -91,27 +94,45 @@ func Ping(dstIP net.IP) (net.HardwareAddr, time.Duration, error) {
9194
9295// PingOverIfaceByName sends an arp ping over interface name 'ifaceName' to 'dstIP'
9396func PingOverIfaceByName (dstIP net.IP , ifaceName string ) (net.HardwareAddr , time.Duration , error ) {
94- if err := validateIP (dstIP ); err != nil {
95- return nil , 0 , err
96- }
97-
98- iface , err := net .InterfaceByName (ifaceName )
99- if err != nil {
100- return nil , 0 , err
101- }
102- return PingOverIface (dstIP , * iface )
97+ return PingWithOptions (dstIP , WithIfaceByName (ifaceName ))
10398}
10499
105100// PingOverIface sends an arp ping over interface 'iface' to 'dstIP'
106101func PingOverIface (dstIP net.IP , iface net.Interface ) (net.HardwareAddr , time.Duration , error ) {
102+ return PingWithOptions (dstIP , WithIface (iface ))
103+ }
104+
105+ // PingWithOptions sends an arp ping to 'dstIP'
106+ func PingWithOptions (dstIP net.IP , options ... Option ) (net.HardwareAddr , time.Duration , error ) {
107107 if err := validateIP (dstIP ); err != nil {
108108 return nil , 0 , err
109109 }
110110
111+ var op = new (Op )
112+ for _ , f := range options {
113+ if err := f (op ); err != nil {
114+ return nil , 0 , err
115+ }
116+ }
117+
118+ if op .timeout == 0 {
119+ op .timeout = timeout
120+ }
121+
122+ if op .iface == nil {
123+ return nil , 0 , ErrNoUsableInterface
124+ }
125+ iface := * op .iface
126+ srcIP := op .srcIP
127+
111128 srcMac := iface .HardwareAddr
112- srcIP , err := findIPInNetworkFromIface (dstIP , iface )
113- if err != nil {
114- return nil , 0 , err
129+
130+ if len (srcIP ) == 0 {
131+ ip , err := findIPInNetworkFromIface (dstIP , iface )
132+ if err != nil {
133+ return nil , 0 , err
134+ }
135+ srcIP = ip
115136 }
116137
117138 broadcastMac := []byte {0xff , 0xff , 0xff , 0xff , 0xff , 0xff }
@@ -162,44 +183,50 @@ func PingOverIface(dstIP net.IP, iface net.Interface) (net.HardwareAddr, time.Du
162183 select {
163184 case pingResult := <- pingResultChan :
164185 return pingResult .mac , pingResult .duration , pingResult .err
165- case <- time .After (timeout ):
186+ case <- time .After (op . timeout ):
166187 sock .deinitialize ()
167188 return nil , 0 , ErrTimeout
168189 }
169190}
170191
171192// GratuitousArp sends an gratuitous arp from 'srcIP'
172193func GratuitousArp (srcIP net.IP ) error {
173- if err := validateIP (srcIP ); err != nil {
174- return err
175- }
176-
177- iface , err := findUsableInterfaceForNetwork (srcIP )
178- if err != nil {
179- return err
180- }
181- return GratuitousArpOverIface (srcIP , * iface )
194+ return GratuitousArpWithOptions (WithSourceIP (srcIP ))
182195}
183196
184197// GratuitousArpOverIfaceByName sends an gratuitous arp over interface name 'ifaceName' from 'srcIP'
185198func GratuitousArpOverIfaceByName (srcIP net.IP , ifaceName string ) error {
186- if err := validateIP (srcIP ); err != nil {
187- return err
188- }
189-
190- iface , err := net .InterfaceByName (ifaceName )
191- if err != nil {
192- return err
193- }
194- return GratuitousArpOverIface (srcIP , * iface )
199+ return GratuitousArpWithOptions (WithSourceIP (srcIP ), WithIfaceByName (ifaceName ))
195200}
196201
197202// GratuitousArpOverIface sends an gratuitous arp over interface 'iface' from 'srcIP'
198203func GratuitousArpOverIface (srcIP net.IP , iface net.Interface ) error {
204+ return GratuitousArpWithOptions (WithSourceIP (srcIP ), WithIface (iface ))
205+ }
206+
207+ // GratuitousArpWithOptions sends an gratuitous arp
208+ func GratuitousArpWithOptions (options ... Option ) error {
209+ var op = new (Op )
210+ for _ , f := range options {
211+ if err := f (op ); err != nil {
212+ return err
213+ }
214+ }
215+
216+ srcIP := op .srcIP
199217 if err := validateIP (srcIP ); err != nil {
200218 return err
201219 }
202220
221+ if op .iface == nil {
222+ iface , err := findUsableInterfaceForNetwork (srcIP )
223+ if err != nil {
224+ return err
225+ }
226+ op .iface = iface
227+ }
228+ iface := * op .iface
229+
203230 srcMac := iface .HardwareAddr
204231 broadcastMac := []byte {0xff , 0xff , 0xff , 0xff , 0xff , 0xff }
205232 request := newArpRequest (srcMac , srcIP , broadcastMac , srcIP )
0 commit comments