This is quite rough in places, all the same, feedback at this point might be
useful.
What I have no was more than enough though to implement an 'ping' program which
uses raw sockets to generate ICMP and ICMP6 packets and read the responses.
There are unresolved issues such as:
- should Dail(...) and Listen(...) support this?
- does "rawip" make sense for the net name?
- how best to deal with the port != proto issue?
etc
Thanks for taking care of this. A bunch of high level things.
Please
hg cp udp.go ipsock.go
mv rawipsock.go ipsock.go
hg rm -f rawipsock.go
This will change the file name to ipsock.go but
more importantly establish udp.go as a base for diffs.
I'd like to call the networks "ip", "ipv4", and "ipv6".
The long name should be IPAddr, IPConn, etc.
I wonder if TCPAddr and UDPAddr should be replaced
by IPAddr too.
type IPAddr struct {
IP IP;
Port int;
}
It's fine for "Port" to mean IP protocol when net == "ip".
Looks like there is a change missing in sock.go:
you added an argument to socket.
Please make the obvious change in syscall_darwin.go too.
I'll test that it works on my machine if you don't have one handy.
Finally, there should be a test.
Thanks.
Russ
On Tue, Mar 23, 2010 at 06:43:10PM -0700, Russ Cox wrote:
> This will change the file name to ipsock.go but more importantly
> establish udp.go as a base for diffs.
i considered that but assumed the codereview extention wouldn't handle
that knowledge
> I'd like to call the networks "ip", "ipv4", and "ipv6".
can do, i want to do ethernet sockets as well, i have an AoE daemon i
wrote some time i could then port to Go
> The long name should be IPAddr, IPConn, etc.
ack
> I wonder if TCPAddr and UDPAddr should be replaced
> by IPAddr too.
can do, but i would prefer that is a separate CL, either as a
precursor or a follow up
which would you prefer?
> type IPAddr struct {
> IP IP;
> Port int;
> }
>
> It's fine for "Port" to mean IP protocol when net == "ip".
except it doesn't map correctly, sending (f.e. an ICMP) you would only
have a host and no port
there is the case of "which" IP proto you want, i fudge that
right now by doing:
laddr, err := net.ResolveRAWIPAddr("[::]:58")
c, err := net.DialRAWIP("rawip6", laddr, nil)
(58 is icmp6)
however, i don't really want to bind at all... and using part of the
string to derive a protocol (for the socket call) and part to derive
an address for bind seems wrong
for sending it's also ugly
conn.SendTo(..., addr)
right now the ping code has:
var hosts = []string{
"[2001:470:400::2]:1", // ns.he.net
"[2001:4810::110]:1", // ip6.me
"[2001:4860:b006::6a]:1", // ipv6.google.com
"[2001:4f8:0:2::d]:1", // isc.org
"[2001:5c0:1000:10::2]:1", // gogo6.com
"[2001:5c0:1400:b:8000:0:4706:c47e]:1", // parsec.stupidest.org
"[2001:dc0:4001:1:0:1836:0:140]:1", // ns4.apnic.net
"[2002:836b:4179::836b:4179]:1", // ipv6.research.microsoft.com
}
notice the trailing :1 ... that's ignored though and just to make sure
the address parser is happy
addr needs to have a trailing port or it won't parse, i could probably
have the callers allow that to be relaxed. i also need to find out
why AAAA resolution isn't working
> Please make the obvious change in syscall_darwin.go too.
i can for compilation sake, but it won't work the way BindToDevice
stuff is
how about (for now) i allow SetsockoptString to be visible from net
and use that where needed
> I'll test that it works on my machine if you don't have one handy.
i do, but i can't test interface binding, it works differently
> Finally, there should be a test.
i have an icmp pinger application, ipv4 and ipv6, i should distill
something from that --- perhaps icmp ping/reply to localhost and
google.com would suffice or is that too high level?
> i considered that but assumed the codereview extention wouldn't handle
> that knowledge
it will.
>> I wonder if TCPAddr and UDPAddr should be replaced
>> by IPAddr too.
>
> can do, but i would prefer that is a separate CL, either as a
> precursor or a follow up
>
> which would you prefer?
leave it as is for now.
>> type IPAddr struct {
>> IP IP;
>> Port int;
>> }
>>
>> It's fine for "Port" to mean IP protocol when net == "ip".
>
> except it doesn't map correctly, sending (f.e. an ICMP) you would only
> have a host and no port
isn't the port the icmp protocol?
otherwise how does it know which IP protocol to use?
> there is the case of "which" IP proto you want, i fudge that
> right now by doing:
>
> laddr, err := net.ResolveRAWIPAddr("[::]:58")
> c, err := net.DialRAWIP("rawip6", laddr, nil)
>
> (58 is icmp6)
>
> however, i don't really want to bind at all... and using part of the
> string to derive a protocol (for the socket call) and part to derive
> an address for bind seems wrong
what does the system call interface look like?
is it different than what's above?
sockaddr_in has a sin_port inside it, even
for SOCK_RAW (raw ip). what is the meaning of that field?
why isn't it correct to set the number there?
i guess i don't understand the problem.
if i want 127.0.0.1 ip protocol 6, what's
wrong with 127.0.0.1:6? is it that the
6 is supposed to be specified using something
other than sin_port, or is it that you don't
think the syntax is correct?
> var hosts = []string{
> "[2001:470:400::2]:1", // ns.he.net
> "[2001:4810::110]:1", // ip6.me
> "[2001:4860:b006::6a]:1", // ipv6.google.com
> "[2001:4f8:0:2::d]:1", // isc.org
> "[2001:5c0:1000:10::2]:1", // gogo6.com
> "[2001:5c0:1400:b:8000:0:4706:c47e]:1", // parsec.stupidest.org
> "[2001:dc0:4001:1:0:1836:0:140]:1", // ns4.apnic.net
> "[2002:836b:4179::836b:4179]:1", //
ipv6.research.microsoft.com
> }
>
> notice the trailing :1 ... that's ignored though and just to make sure
> the address parser is happy
oh i see, it's that the port isn't symmetric?
what happens with the sendto system call?
is sin_port ignored?
> how about (for now) i allow SetsockoptString to be visible from net
> and use that where needed
i'd prefer not to expose the horror that is setsockopt.
> i have an icmp pinger application, ipv4 and ipv6, i should distill
> something from that --- perhaps icmp ping/reply to localhost and
> google.com would suffice or is that too high level?
do you have to be root to get a raw ip socket no matter
what the subprotocol? if so, check os.Getuid() and have the
test just return if it's not root. pinging localhost seems fine:
no need to ping an external address.
russ
On Tue, Mar 23, 2010 at 08:19:29PM -0700, Russ Cox wrote:
> isn't the port the icmp protocol?
sorta kinda not really
> otherwise how does it know which IP protocol to use?
it's an argument to socket that's not used for tcp/udp, icmp doesn't
have ports
in fact, when you ping out, and watch for packets coming back, you can
see other packets sometimes (like icmp6 neigh packets)
> what does the system call interface look like?
tcp:
s = socket(AF_INET, SOCK_STREAM, 0);
connect(s, &addr, addrlen); // address port matters
udp:
s = socket(AF_INET, SOCK_DGRAM, 0);
connect(s, &addr, addrlen); // address port matters
rawip:
s = socket(AF_INET, SOCK_RAW, ip_proto); // proto/port needed here
connect(s, &addr, addrlen); // port ignored
> if i want 127.0.0.1 ip protocol 6, what's
> wrong with 127.0.0.1:6?
nothing, but the port is a feature of the socket when it's created,
it's not part of bind/connect as it is for tcp/udp
the interface issues mean that you *MUST* for Dial supply a local
address to get the protocol from, for tcp/udp you can omit this. on
balance i think this is reasonable at this point
if you agree then i should probably change hostPortToIP to be
something like:
// Convert "host:port" into IP address and port. If requireport is
// false then the port can be ommitted and will be returned as zero
func hostPortToIP(net, hostport string, requireport bool) (ip IP, iport int, err
os.Error)
and then verify it can parse with at least the following forms:
example.com
example.com:80
1.2.3.4
1.2.3.5:80
:80
[0:0:0:0:0:0:1]
[0::1]
[::1]
[0:0:0:0:0:0:1]:80
[0::1]:80
[::1]:80
> oh i see, it's that the port isn't symmetric?
sendto needs no port
recvfrom has none
> what happens with the sendto system call?
> is sin_port ignored?
yes
> i'd prefer not to expose the horror that is setsockopt
see, i actually don't think setsockopt is that bad
BindToDevice is needed for multicast/broadcast because unicast routing
won't work
what if (for now) we had arch specific net glue to avoid that? and i
put BindToDevice in the linux version and ignore it in the others, it
means users can use this for linux and it won't compile elsewhere
until i work out those details?
> do you have to be root to get a raw ip socket no matter
> what the subprotocol?
yes
> if so, check os.Getuid() and have the
> test just return if it's not root.
is the test harness that's fine, in net/ i would argue it's out of
place
> pinging localhost seems fine: no need to ping an external address.
ok
I still think that it makes sense to use the host:port syntax here
rather than invent something else. The subprotocol has to be
specified somehow, and that syntax is as good as any and
consistent with the rest of the package.
I'd suggest saying that for Dial with net == "ip", laddr and raddr
are still host:port (or empty) and the ports must match.
Various alternatives (different requirements for laddr, raddr, letting
one of them be zero, silently ignoring one of them when they
don't match) all seem worse.
The IP-specific functions would then be:
func DialIP(net string, laddr, raddr *IPAddr) (c *IPConn, err os.Error)
func ListenIP(net string, laddr *IPAddr) (c *IPConn, err os.Error)
func ResolveIPAddr(addr string) (*IPAddr, os.Error)
LookupPort should load /etc/protocols to get protocol names
so that you can say "127.0.0.1:icmp" on the "ip" network
the same way you can say "127.0.0.1:http" on the "tcp" network.
Russ
On Tue, Mar 23, 2010 at 10:38:59PM -0700, Russ Cox wrote:
> I still think that it makes sense to use the host:port syntax here
> rather than invent something else.
i agree
> I'd suggest saying that for Dial with net == "ip", laddr and raddr
> are still host:port (or empty) and the ports must match.
raddr's port isn't needed, i'll make a note that if specified it
should match
using port (proto) == 0 for 'not given' actually won't work, 0 is a
valid number, but -1 seems unlikely to ever be useful
> Various alternatives (different requirements for laddr, raddr,
> letting one of them be zero, silently ignoring one of them when they
> don't match) all seem worse.
ok
> func DialIP(net string, laddr, raddr *IPAddr) (c *IPConn, err os.Error)
laddr & raddr _required_
> func ListenIP(net string, laddr *IPAddr) (c *IPConn, err os.Error)
laddr required
> func ResolveIPAddr(addr string) (*IPAddr, os.Error)
allow this to work for host only variations
> LookupPort should load /etc/protocols to get protocol names so that
> you can say "127.0.0.1:icmp" on the "ip" network the same way you
> can say "127.0.0.1:http" on the "tcp" network.
i planned to do that, i was being lazy :-)
>> I'd suggest saying that for Dial with net == "ip", laddr and raddr
>> are still host:port (or empty) and the ports must match.
>
> raddr's port isn't needed, i'll make a note that if specified it
> should match
i don't think there's an "if specified". it should always be specified.
allowing the :port to be dropped sometimes leads to
convoluted explanations of exactly when.
russ
On Wed, Mar 24, 2010 at 12:13:24AM -0700, Russ Cox wrote:
> i don't think there's an "if specified". it should always be
> specified.
hmm, really?
it means to ping you end up doing:
addr, err := Resolve...("[::]:1234")
c.WriteToIP(pkt, addr)
and the 1234 would be completely ignored ... and from WriteTo(..) i
could check this by extended the IPConn structure i guess
> allowing the :port to be dropped sometimes leads to
> convoluted explanations of exactly when.
but it allows you to put in bogus/ignored junk
On Tue, Mar 23, 2010 at 06:43:10PM -0700, Russ Cox wrote:
> hg cp udp.go ipsock.go
there is already ipsock.go
i moved that to ipcommon.go for now, it's maybe a bit over the top but
i think there is more room to refactoring here long term so probably
acceptable
now, that saig ... hg diff works weirdly, it diffs against the
ipsock.go that i renamed...
> I'd like to call the networks "ip", "ipv4", and "ipv6".
i did this, BUT, we have udp, udp4, udp6, tcp, tcp4, tcp6, etc
we don't have udpv4, udpv6, etc
> The long name should be IPAddr, IPConn, etc.
done
> I wonder if TCPAddr and UDPAddr should be replaced
> by IPAddr too.
i will do that some other time, moving the common parts out into
ipcommon.go
> Looks like there is a change missing in sock.go:
> you added an argument to socket.
fixed
> Please make the obvious change in syscall_darwin.go too.
done, and for freebsd
On Wed, Mar 24, 2010 at 08:44:07PM -0700, Russ Cox wrote:
> looking at http://codereview.appspot.com/684041/show
> i don't see the new patch.
sorry, hg upload is failing
Got error status from ['hg', 'diff', '--git', '-r', '4de2f2e80906',
'src/pkg/net/Makefile', 'src/pkg/net/ipsock.go', 'src/pkg/net/net.go',
'src/pkg/net/tcpsock.go', 'src/pkg/net/udpsock.go',
'src/pkg/syscall/syscall_linux.go', 'src/pkg/net/ipcommon.go',
'src/pkg/syscall/syscall_darwin.go',
'src/pkg/syscall/syscall_freebsd.go', 'src/pkg/net/port.go']:
[...]
i think it dislikes the upload/rename/screw about/upload, etc
i might just drop it and make a new CL
give me a few mins, i have to go read about princesses to a small
child then ill fix this :-)
Closer, most comments addresses.
I think it should be split up though to:
1. syscall changes
2. rename ipsock.go to ipcommon.go
3. basic raw socket implementation (w/ test)
4. as yet unresolved BindToDevice stuff
Should compile everywhere, might even work.
Test case added where a raw ipv4 socket is used to ping localhost.
I'd still like some feedback on ipv4,ipv6 vs ip4,ip6 and any commend on
BindToDevice as it now stands would be appreciated.
http://codereview.appspot.com/684041/diff/42008/43002 File src/pkg/net/iprawsock.go (right): http://codereview.appspot.com/684041/diff/42008/43002#newcode25 src/pkg/net/iprawsock.go:25: // IPAddr represents the address of a IP end ...
On Sun, Mar 28, 2010 at 07:59:49AM +0000, rsc@golang.org wrote:
> http://codereview.appspot.com/684041/diff/42008/43002#newcode25
> src/pkg/net/iprawsock.go:25: // IPAddr represents the address of a IP
> end point.
> I wonder if we should move the methods onto IP and
> just use IP instead of IPAddr.
can do, i was thinking of doing that as a later CL and maybe unifying
all address types
> http://codereview.appspot.com/684041/diff/42008/43002#newcode377
> src/pkg/net/iprawsock.go:377: if syscall.OS != "linux" {
> ugh. delete
it won't work elsewhere (yet) ... so just let weirdness happen if it's
used there?
> http://codereview.appspot.com/684041/diff/42008/43002#newcode380
> src/pkg/net/iprawsock.go:380: const SO_BINDTODEVICE = 0x19
> move to syscall
syscall.SO_BINDTODEVICE already exists but ONLY for linux, there are
some comments on what other OS (might) need
i put it there so the code would compile everywhere but for now only
linux would support BindToDevice
how about i just yank this code completely for now and introduce it in
a later CL to try and keep the size of the basics down? the only
concern i have with that is i really do want something like this
functionality, not just for ip sockets but also udp
> You were right about the names: "ip4" and "ip6" are better.
will revert
> please name the file ipraw_test.go to match iprawsock.go.
> should be Copyright 2010, too
ok
> src/pkg/net/rawip_test.go:58: func TestRawIPSocket(t *testing.T) {
> func TestICMP
ok
On Wed, May 5, 2010 at 01:16, <cw@f00f.org> wrote: > Ping. > > Should I ...
14 years, 11 months ago
(2010-05-05 08:26:29 UTC)
#30
On Wed, May 5, 2010 at 01:16, <cw@f00f.org> wrote:
> Ping.
>
> Should I shelve this for now?
Sorry this ended up on the back burner for so long.
On a quick scan, it looks good.
The doc comment for BindToDevice doesn't start
with a complete sentence but should.
I'm not thrilled with the BindToDevice implementation.
That's the kind of thing that will just sit there broken
for a long time. Can we do it right instead, with proper
support in package syscall for all the operating systems,
as a separate CL?
Russ
On Wed, May 05, 2010 at 01:26:25AM -0700, Russ Cox wrote: > The doc comment ...
14 years, 11 months ago
(2010-05-05 08:49:14 UTC)
#31
On Wed, May 05, 2010 at 01:26:25AM -0700, Russ Cox wrote:
> The doc comment for BindToDevice doesn't start
> with a complete sentence but should.
' enough :)
> I'm not thrilled with the BindToDevice implementation.
now am i
> That's the kind of thing that will just sit there broken
> for a long time.
it's not broken, it's just not implemented everywhrere
> Can we do it right instead, with proper support in package syscall
> for all the operating systems, as a separate CL?
we can, but i don't know off the top of my head how to do it, other
than the URLs comments i put in the source
certainly i'll try to work something out (maybe nmap source is worth
looking at, i assume that's been ported to just about everything)
even a CL that added stubs for the other systems so that the TODO was ...
14 years, 11 months ago
(2010-05-05 16:39:03 UTC)
#33
even a CL that added stubs for the other systems
so that the TODO was in package syscall would
be better than hard-coding freebsd constants in
package net.
http://codereview.appspot.com/684041/diff/99001/100003
File src/pkg/net/iprawsock.go (right):
http://codereview.appspot.com/684041/diff/99001/100003#newcode347
src/pkg/net/iprawsock.go:347: // BindToDevice is used to bind a socket to an
inteface. This is
// BindToDevice requires the connection c to use the named network interface.
// It is most commonly used when sending to broadcast or multicast addresses.
LGTM Please fix the doc comment. http://codereview.appspot.com/684041/diff/116001/117003 File src/pkg/net/iprawsock.go (right): http://codereview.appspot.com/684041/diff/116001/117003#newcode343 src/pkg/net/iprawsock.go:343: // BindToDevice is ...
14 years, 10 months ago
(2010-05-20 16:49:24 UTC)
#36
LGTM
Please fix the doc comment.
http://codereview.appspot.com/684041/diff/116001/117003
File src/pkg/net/iprawsock.go (right):
http://codereview.appspot.com/684041/diff/116001/117003#newcode343
src/pkg/net/iprawsock.go:343: // BindToDevice is used to bind a socket to an
inteface. This is
Please avoid the name socket in the doc comments.
Package net does not need to be about sockets.
// BindToDevice binds an IPConn to a network interface.
the "This is needed" is probably unnecessary.
Issue 684041: code review 684041: net: implement raw sockets
(Closed)
Created 15 years ago by cw
Modified 14 years, 10 months ago
Reviewers:
Base URL:
Comments: 18