pastebin - collaborative debugging tool
rovema.kpaste.net RSS

Difference between
modified post eeb6493 by Anonymous on Mon 17th Jul 2023 15:25
original post 56a4a5f43 by Anonymous on Tue 11th Jul 2023 16:40
Download diff
Show old version | new version | both versions

    
11
#!/usr/bin/ksh93
2+
23
#
34
# sshnfs - remote login client with NFSv4 forwarding
45
#
6+
58
# Example usage:
9+
# $ ksh sshnfs.ksh -o NFSURL=ssh+nfs://localhost/export/home/rmainz root@10.49.28.10 #
610
# $ ksh sshnfs.ksh -o NFSURL=nfs://localhost/export/home/rmainz root@10.49.20.207 #
7-
# $ ksh sshnfs.ksh -o NFSURL=nfs://derfwpc5131/export/home/rmainz -o NFSJumphost=rmainz@derfwpc5131,roland.mainz@derfwnb8353 -J rmainz@derfwpc5131,roland.mainz@derfwnb8353 root@10.49.20.207
11+
# $ ksh sshnfs.ksh -o NFSURL=nfs://derfwpc5131/export/home/rmainz root@10.49.28.10 #
8-
# $ ksh sshnfs.ksh -o NFSURL=nfs://derfwpc5131/export/home/rmainz target@fe80::d6f5:27ff:fe2b:8588%enp2s0
12+
# $ ksh sshnfs.ksh -o NFSURL=ssh+nfs://derfwpc5131/export/home/rmainz -o SSHNFSJumphost=rmainz@derfwpc5131,roland.mainz@derfwnb8353 -J rmainz@derfwpc5131,roland.mainz@derfwnb8353 root@10.49.20.207
9-
# $ ksh sshnfs.ksh -o NFSServerSSHLoginName=root -o NFSURL=nfs://derfwpc5131/export/home/rmainz root@10.49.28.56
13+
# $ ksh sshnfs.ksh -o NFSURL=ssh+nfs://derfwpc5131/export/home/rmainz target@fe80::d6f5:27ff:fe2b:8588%enp2s0
10-
# $ SSHNFS_OPTIONS='-o NFSServerSSHLoginName=root -o NFSURL=nfs://derfwpc5131/export/home/rmainz' sshnfs.ksh root@10.49.28.56
14+
# $ ksh sshnfs.ksh -o NFSServerSSHLoginName=root -o NFSURL=ssh+nfs://derfwpc5131/export/home/rmainz root@10.49.28.56
15+
# $ SSHNFS_OPTIONS='-o NFSServerSSHLoginName=root -o NFSURL=ssh+nfs://derfwpc5131/export/home/rmainz' sshnfs.ksh root@10.49.28.56
1116
#
1217
# Written by Roland Mainz <roland.mainz@nrubsig.org>
1318
#
1419
1520
#
1621
# simple netstat -n parser
1722
#
1823
function netstat_list_connections
1924
{
2025
	set -o nounset
2126
	nameref data=$1
2227
2328
	compound out=( typeset stdout stderr ; integer res )
2429
2530
	out.stderr="${ { out.stdout="${ LC_ALL='POSIX' PATH='/usr/bin:/bin' netstat -a -n ; (( out.res=$? )) ; }" ; } 2>&1 ; }"
2631
	if (( out.res != 0 )) || [[ ${out.stderr} != '' ]] ; then
2732
		return 1
2833
	fi
2934
3035
	typeset -a data.connections
3136
	typeset l
3237
	integer dci=0 # data.connections array index
3338
3439
	while read l ; do
3540
		leftover="${l/~(Elrx)
3641
		(?: # non-capturing group
3742
			#
3843
			# regex group for tcp,udp
3944
			#
4045
			(tcp|tcp6|udp|udp6|raw|raw6|sctp|sctp6)	# Proto
4146
			[[:space:]]+
4247
			([[:digit:]]+)			# Recv-Q
4348
			[[:space:]]+
4449
			([[:digit:]]+)			# Send-Q
4550
			[[:space:]]+
4651
			([^[:space:]]+)			# Local Address
4752
			[[:space:]]+
4853
			([^[:space:]]+)			# Foreign Address
4954
			(?:
5055
				|
5156
				[[:space:]]+
5257
				([^[:space:]]*?) 	# State (Optional)
5358
			)
5459
		|
5560
			#
5661
			# regex for unix
5762
			#
5863
			(unix)				# Proto
5964
			[[:space:]]+
6065
			([[:digit:]]+)			# RefCnt
6166
			[[:space:]]+
6267
			(\[.+?\])			# Flags
6368
			[[:space:]]+
6469
			([^[:space:]]+) 		# Type
6570
			[[:space:]]+
6671
			([^[:space:]]*?)		# State (optional)
6772
			[[:space:]]+
6873
			([[:digit:]]+)			# I-Node
6974
			(?:
7075
				|
7176
				[[:space:]]+
7277
				([^[:space:]]+)		# Path (optional)
7378
			)
7479
		)
7580
			/X}"
7681
7782
		# If the regex above did not match then .sh.match
7883
		# remains untouched, so we might see data from the
7984
		# previous round.
8085
		# So we check the "leftover" var whether it just
8186
		# contains the dummy value of "X" to indicate a
8287
		# successful regex match
8388
		if [[ "$leftover" == 'X' ]] ; then
8489
			#print -v .sh.match
8590
8691
			if [[ "${.sh.match[1]-}" != '' ]] ; then
8792
				nameref dcn=data.connections[$dci]
8893
8994
				typeset dcn.proto="${.sh.match[1]}"
9095
				typeset dcn.recv_q="${.sh.match[2]}"
9196
				typeset dcn.send_q="${.sh.match[3]}"
9297
				typeset dcn.local_address="${.sh.match[4]}"
9398
				typeset dcn.foreign_address="${.sh.match[5]}"
9499
				typeset dcn.state="${.sh.match[6]}"
95100
				((dci++))
96101
			elif [[ "${.sh.match[7]-}" != '' ]] ; then
97102
				nameref dcn=data.connections[$dci]
98103
99104
				typeset dcn.proto="${.sh.match[7]}"
100105
				typeset dcn.refcnt="${.sh.match[8]}"
101106
				typeset dcn.flags="${.sh.match[9]}"
102107
				typeset dcn.type="${.sh.match[10]}"
103108
				[[ "${.sh.match[11]}" != '' ]] && typeset dcn.state="${.sh.match[11]}"
104109
				typeset dcn.inode="${.sh.match[12]}"
105110
				[[ "${.sh.match[13]}" != '' ]] && typeset dcn.path="${.sh.match[13]}"
106111
				((dci++))
107112
			fi
108113
		else
109114
			true
110115
			#printf $"leftover=%q\n" "${leftover}"
111116
		fi
112117
	done <<<"${out.stdout}"
113118
114119
	return 0
115120
}
116121
117122
function netstat_list_active_local_tcp_connections
118123
{
119124
	set -o nounset
120125
	nameref ar=$1
121126
	compound c
122127
	integer port
123128
	integer i
124129
125130
	netstat_list_connections c || return 1
126131
	#print -v c
127132
128133
	[[ -v ar ]] || integer -a ar
129134
130135
	for i in "${!c.connections[@]}" ; do
131136
		nameref n=c.connections[$i]
132137
133138
		# look for only for TCP connections which match
134139
		# 127.0.*.* or IPv6 ::1 for localhost
135140
		# 0.0.0.0 or IPv6 :: for all addresses (e.g. servers)
136141
		if [[ "${n.proto}" == ~(El)tcp && \
137142
			"${n.local_address}" == ~(Elr)((127\.0\..+|::1)|(::|0\.0\.0\.0|)):[[:digit:]]+ ]] ; then
138143
139144
			port="${n.local_address##*:}"
140145
			#printf $"port = %d\n" port
141146
142147
			(( ar[port]=1 ))
143148
		fi
144149
	done
145150
146151
	return 0
147152
}
148153
149154
function netstat_find_next_free_local_tcp_port
150155
{
151156
	set -o nounset
152157
	compound c=( integer -a ar )
153158
	nameref ret_free_port=$1
154159
	integer start_port
155160
	integer end_port
156161
	integer i
157162
158163
	netstat_list_active_local_tcp_connections c.ar || return 1
159164
160165
	#print -v c
161166
162167
	(( start_port=$2 ))
163168
	if (( $# > 2 )) ; then
164169
		(( end_port=$3 ))
165170
	else
166171
		(( end_port=65535 ))
167172
	fi
168173
169174
	for ((i=start_port ; i < end_port ; i++ )) ; do
170175
		if [[ ! -v c.ar[i] ]] ; then
171176
			(( ret_free_port=i ))
172177
			return 0
173178
		fi
174179
	done
175180
176181
	return 1
177182
}
178183
179184
#
180185
# parse url
181186
#
182187
# returns:
183188
# data.protocol
184189
# data.host
185190
# data.port (optional)
186191
# data.path
187192
#
188193
function parse_url
189194
{
190195
	typeset url="$2"
191196
	typeset leftover
192197
	nameref data="$1"
193198
194199
	# ~(E) is POSIX extended regular expression matching (instead of
195200
	# shell pattern)
196201
	leftover="${url//~(Elr)(.+?):\/\/(.+?)(?:|:([[:digit:]]+))(?:\/(.*?))?/X}"
197202
198203
	# All parsed data should be captured via eregex in .sh.match - if
199204
	# there is anything left (except the 'X') then the input string did not
200205
	# properly match the eregex
201206
	[[ "$leftover" == 'X' ]] || { print -u2 -f $"%s: Parser error\n" "$0" ; return 1 ; }
202207
203208
	data.protocol="${.sh.match[1]}"
204209
	data.host="${.sh.match[2]}"
205210
	# bug: should be [[ -v .sh.match[3] ]], but ksh93u has bugs
206211
	[[ "${.sh.match[3]}" != '' ]] && integer data.port="${.sh.match[3]}"
207212
	data.path="${.sh.match[4]}"
208213
209214
	return 0
210215
}
211216
212-
function parse_nfs_url
217+
function parse_sshnfs_url
213218
{
214219
	typeset url="$2"
215220
	nameref data="$1"
216221
217222
	parse_url data "$url" || return 1
218223
219-
	[[ "${data.protocol}" == 'nfs' ]]	|| { print -u2 -f $"%s: Not a NFS url\n" "$0" ; return 1 ; }
224+
	[[ "${data.protocol}" == ~(Elr)(ssh\+nfs|nfs) ]] || \
220-
	[[ "${data.host}" != '' ]]		|| { print -u2 -f $"%s: NFS hostname missing\n" "$0" ; return 1 ; }
225+
		{ print -u2 -f $"%s: Not a nfs:// or ssh+nfs:// url\n" "$0" ; return 1 ; }
221-
	[[ "${data.path}" != '' ]]		|| { print -u2 -f $"%s: NFS path missing\n" "$0" ; return 1 ; }
226+
	[[ "${data.host}" != '' ]] || { print -u2 -f $"%s: NFS hostname missing\n" "$0" ; return 1 ; }
227+
	[[ "${data.path}" != '' ]] || { print -u2 -f $"%s: NFS path missing\n" "$0" ; return 1 ; }
222228
223229
	if [[ ! -v data.port ]] ; then
224230
		# use # default NFSv4 TCP port number (see
225231
		# $ getent services nfs #)
226232
		integer data.port=2049
227233
	fi
228234
229235
	return 0
230236
}
231237
232238
233239
function main
234240
{
235241
	set -o nounset
236242
	typeset mydebug=false # fixme: should be "bool" for ksh93v
237243
	integer i
238244
	integer retval
239245
	compound c=(
240246
		# User name for SSH login to NFS server
241247
		typeset nfsserver_ssh_login_name="$LOGNAME"
248+
	)
242249
244-
		integer local_forward_port
245250
246-
		# TCP port on destination machine where we forward the
247-
		# NFS port from the server
248-
		integer destination_nfs_port=33049
249251
250-
		typeset ssh_control_socket_name="/tmp/sshnfs_ssh-control-socket_logname${LOGNAME}_ppid${PPID}_pid$$"
251-
	)
252-
252+
	#

Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:

To highlight particular lines, prefix each line with {%HIGHLIGHT}




All content is user-submitted.
The administrators of this site (kpaste.net) are not responsible for their content.
Abuse reports should be emailed to us at