Skip to content

Commit 7faa7a8

Browse files
authored
Add netcat
Initial netcat commit
2 parents b4c6d51 + 3622469 commit 7faa7a8

File tree

3 files changed

+192
-1
lines changed

3 files changed

+192
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
ROOT_DIR=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
44
# TODO: missing roughtime/timeserver roughtime/timeclient
5-
SRCDIRS= helloworld sensorapp/sensorserver sensorapp/sensorfetcher camerapp/imageserver camerapp/imagefetcher bwtester/bwtestserver bwtester/bwtestclient webapp bat bat/example_server tools/pathdb_dump
5+
SRCDIRS= helloworld sensorapp/sensorserver sensorapp/sensorfetcher camerapp/imageserver camerapp/imagefetcher bwtester/bwtestserver bwtester/bwtestclient webapp bat bat/example_server tools/pathdb_dump netcat
66
TARGETS = $(foreach D,$(SRCDIRS),$(D)/$(notdir $(D)))
77

88
all: $(TARGETS)

netcat/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# scion-netcat
2+
A SCION port of the netcat process.
3+
4+
5+
## Usage
6+
```./netcat <host> <port>```
7+
8+
See `./netcat -h` for more.
9+

netcat/main.go

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"flag"
6+
"fmt"
7+
"io"
8+
golog "log"
9+
"os"
10+
"strconv"
11+
"sync"
12+
13+
quic "github.com/lucas-clemente/quic-go"
14+
"github.com/netsec-ethz/scion-apps/lib/scionutil"
15+
scionlog "github.com/scionproto/scion/go/lib/log"
16+
"github.com/scionproto/scion/go/lib/snet"
17+
"github.com/scionproto/scion/go/lib/snet/squic"
18+
19+
log "github.com/inconshreveable/log15"
20+
)
21+
22+
func printUsage() {
23+
fmt.Println("netcat [flags] host-address port")
24+
fmt.Println("netcat [flags] -l port")
25+
fmt.Println("The host address is specified as ISD-AS,[IP Address]")
26+
fmt.Println("Example SCION address: 17-ffaa:1:bfd,[127.0.0.1]:42002")
27+
fmt.Println("Available flags:")
28+
fmt.Println(" -h: Show help")
29+
fmt.Println(" -local: Local SCION address (default localhost)")
30+
fmt.Println(" -b: Send or expect an extra (throw-away) byte before the actual data")
31+
fmt.Println(" -tlsKey: TLS key path, only needed when listening (default: ./key.pem)")
32+
fmt.Println(" -tlsCertificate: TLS certificate path, only needed when listening (default: ./certificate.pem)")
33+
}
34+
35+
func main() {
36+
scionlog.SetupLogConsole("debug")
37+
38+
log.Debug("Launching netcat")
39+
40+
var (
41+
remoteAddressString string
42+
port uint16
43+
localAddrString string
44+
45+
quicTLSKeyPath string
46+
quicTLSCertificatePath string
47+
48+
extraByte bool
49+
listen bool
50+
)
51+
flag.Usage = printUsage
52+
flag.StringVar(&remoteAddressString, "local", "", "Local address string")
53+
flag.StringVar(&quicTLSKeyPath, "tlsKey", "./key.pem", "TLS key path")
54+
flag.StringVar(&quicTLSCertificatePath, "tlsCert", "./certificate.pem", "TLS certificate path")
55+
flag.BoolVar(&extraByte, "b", false, "Expect extra byte")
56+
flag.BoolVar(&listen, "l", false, "Listen mode")
57+
flag.Parse()
58+
59+
tail := flag.Args()
60+
if !(len(tail) == 1 && listen) && !(len(tail) == 2 && !listen) {
61+
printUsage()
62+
golog.Panicf("Incorrect number of arguments! Arguments: %v", tail)
63+
}
64+
65+
remoteAddressString = tail[0]
66+
port64, err := strconv.ParseUint(tail[len(tail)-1], 10, 16)
67+
if err != nil {
68+
printUsage()
69+
golog.Panicf("Can't parse port string %v: %v", port64, err)
70+
}
71+
port = uint16(port64)
72+
73+
if localAddrString == "" {
74+
localAddrString, err = scionutil.GetLocalhostString()
75+
if err != nil {
76+
golog.Panicf("Error getting localhost: %v", err)
77+
}
78+
}
79+
80+
localAddr, err := snet.AddrFromString(localAddrString)
81+
if err != nil {
82+
golog.Panicf("Error parsing local address: %v", err)
83+
}
84+
85+
// Initialize SCION library
86+
err = scionutil.InitSCION(localAddr)
87+
if err != nil {
88+
golog.Panicf("Error initializing SCION connection: %v", err)
89+
}
90+
91+
var (
92+
sess quic.Session
93+
stream quic.Stream
94+
)
95+
96+
if listen {
97+
err := squic.Init(quicTLSKeyPath, quicTLSCertificatePath)
98+
if err != nil {
99+
golog.Panicf("Error initializing squic: %v", err)
100+
}
101+
102+
sess, stream = doListen(localAddr, extraByte)
103+
} else {
104+
remoteAddr, err := snet.AddrFromString(fmt.Sprintf("%s:%v", remoteAddressString, port))
105+
if err != nil {
106+
golog.Panicf("Can't parse remote address %s: %v", remoteAddressString)
107+
}
108+
109+
sess, stream = doDial(localAddr, remoteAddr, extraByte)
110+
}
111+
112+
close := func() {
113+
err := stream.Close()
114+
if err != nil {
115+
log.Warn("Error closing stream: %v", err)
116+
}
117+
err = sess.Close(nil)
118+
if err != nil {
119+
log.Warn("Error closing session: %v", err)
120+
}
121+
}
122+
123+
var once sync.Once
124+
go func() {
125+
io.Copy(os.Stdout, stream)
126+
once.Do(close)
127+
}()
128+
io.Copy(stream, os.Stdin)
129+
once.Do(close)
130+
}
131+
132+
func doListen(localAddr *snet.Addr, extraByte bool) (quic.Session, quic.Stream) {
133+
listener, err := squic.ListenSCION(nil, localAddr, &quic.Config{KeepAlive: true})
134+
if err != nil {
135+
golog.Panicf("Can't listen on address %v: %v", localAddr, err)
136+
}
137+
138+
sess, err := listener.Accept()
139+
if err != nil {
140+
golog.Panicf("Can't accept listener: %v", err)
141+
}
142+
143+
stream, err := sess.AcceptStream()
144+
if err != nil {
145+
golog.Panicf("Can't accept stream: %v", err)
146+
}
147+
148+
log.Debug("Connected!")
149+
150+
if extraByte {
151+
(*bufio.NewReader(stream)).ReadByte()
152+
153+
log.Debug("Received extra byte!")
154+
}
155+
156+
return sess, stream
157+
}
158+
159+
func doDial(localAddr, remoteAddr *snet.Addr, extraByte bool) (quic.Session, quic.Stream) {
160+
sess, err := squic.DialSCION(nil, localAddr, remoteAddr, &quic.Config{KeepAlive: true})
161+
if err != nil {
162+
golog.Panicf("Can't dial remote address %v: %v", remoteAddr, err)
163+
}
164+
165+
stream, err := sess.OpenStreamSync()
166+
if err != nil {
167+
golog.Panicf("Can't open stream: %v", err)
168+
}
169+
170+
log.Debug("Connected!")
171+
172+
if extraByte {
173+
_, err := stream.Write([]byte{71})
174+
if err != nil {
175+
golog.Panicf("Error writing extra byte: %v", err)
176+
}
177+
178+
log.Debug("Sent extra byte!")
179+
}
180+
181+
return sess, stream
182+
}

0 commit comments

Comments
 (0)