1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2009-2019. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21-module(ssh_tcpip_forward_srv).
22
23-behaviour(ssh_server_channel).
24
25-record(state, {
26          id, cm,
27          fwd_socket
28	 }).
29
30-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
31
32init([FwdSocket]) ->
33    {ok, #state{fwd_socket=FwdSocket}}.
34
35
36handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, State) ->
37    {ok, State#state{id = ChannelId,
38		     cm = ConnectionManager}};
39
40handle_msg({tcp,Sock,Data}, #state{fwd_socket = Sock,
41                                   cm = CM,
42                                   id = ChId} = State) ->
43    ssh_connection:send(CM, ChId, Data),
44    inet:setopts(Sock, [{active,once}]),
45    {ok, State};
46
47handle_msg({tcp_closed,Sock}, #state{fwd_socket = Sock,
48                                     cm = CM,
49                                     id = ChId} = State) ->
50    ssh_connection:send_eof(CM, ChId),
51    {stop, ChId, State#state{fwd_socket=undefined}}.
52
53
54
55handle_ssh_msg({ssh_cm, _CM, {data, _ChannelId, _Type, Data}}, #state{fwd_socket=Sock} = State) ->
56    gen_tcp:send(Sock, Data),
57    {ok, State};
58
59handle_ssh_msg({ssh_cm, _CM, {eof, ChId}}, State) ->
60    {stop, ChId, State};
61
62handle_ssh_msg({ssh_cm, _CM, {signal, _, _}}, State) ->
63    %% Ignore signals according to RFC 4254 section 6.9.
64    {ok, State};
65
66handle_ssh_msg({ssh_cm, _CM, {exit_signal, ChId, _, _Error, _}}, State) ->
67    {stop, ChId,  State};
68
69handle_ssh_msg({ssh_cm, _, {exit_status, ChId, _Status}}, State) ->
70    {stop, ChId, State}.
71
72
73terminate(_Reason, #state{fwd_socket=Sock}) ->
74    gen_tcp:close(Sock),
75    ok.
76