1/* 2 Unix SMB/CIFS implementation. 3 4 endpoint server for the echo pipe 5 6 Copyright (C) Andrew Tridgell 2003 7 Copyright (C) Stefan (metze) Metzmacher 2005 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21*/ 22 23#include "includes.h" 24#include "system/filesys.h" 25#include "rpc_server/dcerpc_server.h" 26#include "librpc/gen_ndr/ndr_echo.h" 27#include "lib/events/events.h" 28 29 30static NTSTATUS dcesrv_echo_AddOne(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_AddOne *r) 31{ 32 *r->out.out_data = r->in.in_data + 1; 33 return NT_STATUS_OK; 34} 35 36static NTSTATUS dcesrv_echo_EchoData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_EchoData *r) 37{ 38 if (!r->in.len) { 39 return NT_STATUS_OK; 40 } 41 42 r->out.out_data = talloc_memdup(mem_ctx, r->in.in_data, r->in.len); 43 if (!r->out.out_data) { 44 return NT_STATUS_NO_MEMORY; 45 } 46 47 return NT_STATUS_OK; 48} 49 50static NTSTATUS dcesrv_echo_SinkData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_SinkData *r) 51{ 52 return NT_STATUS_OK; 53} 54 55static NTSTATUS dcesrv_echo_SourceData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_SourceData *r) 56{ 57 int i; 58 59 r->out.data = talloc_array(mem_ctx, uint8_t, r->in.len); 60 if (!r->out.data) { 61 return NT_STATUS_NO_MEMORY; 62 } 63 64 for (i=0;i<r->in.len;i++) { 65 r->out.data[i] = i; 66 } 67 68 return NT_STATUS_OK; 69} 70 71static NTSTATUS dcesrv_echo_TestCall(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestCall *r) 72{ 73 *r->out.s2 = talloc_strdup(mem_ctx, r->in.s1); 74 if (r->in.s1 && !*r->out.s2) { 75 return NT_STATUS_NO_MEMORY; 76 } 77 return NT_STATUS_OK; 78} 79 80static NTSTATUS dcesrv_echo_TestCall2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestCall2 *r) 81{ 82 r->out.info = talloc(mem_ctx, union echo_Info); 83 if (!r->out.info) { 84 return NT_STATUS_NO_MEMORY; 85 } 86 87 switch (r->in.level) { 88 case 1: 89 r->out.info->info1.v = 10; 90 break; 91 case 2: 92 r->out.info->info2.v = 20; 93 break; 94 case 3: 95 r->out.info->info3.v = 30; 96 break; 97 case 4: 98 r->out.info->info4.v = 40; 99 break; 100 case 5: 101 r->out.info->info5.v1 = 50; 102 r->out.info->info5.v2 = 60; 103 break; 104 case 6: 105 r->out.info->info6.v1 = 70; 106 r->out.info->info6.info1.v= 80; 107 break; 108 case 7: 109 r->out.info->info7.v1 = 80; 110 r->out.info->info7.info4.v = 90; 111 break; 112 default: 113 return NT_STATUS_INVALID_LEVEL; 114 } 115 116 return NT_STATUS_OK; 117} 118 119static NTSTATUS dcesrv_echo_TestEnum(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestEnum *r) 120{ 121 r->out.foo2->e1 = ECHO_ENUM2; 122 return NT_STATUS_OK; 123} 124 125static NTSTATUS dcesrv_echo_TestSurrounding(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestSurrounding *r) 126{ 127 if (!r->in.data) { 128 r->out.data = NULL; 129 return NT_STATUS_OK; 130 } 131 132 r->out.data = talloc(mem_ctx, struct echo_Surrounding); 133 if (!r->out.data) { 134 return NT_STATUS_NO_MEMORY; 135 } 136 r->out.data->x = 2 * r->in.data->x; 137 r->out.data->surrounding = talloc_zero_array(mem_ctx, uint16_t, r->out.data->x); 138 if (!r->out.data->surrounding) { 139 return NT_STATUS_NO_MEMORY; 140 } 141 142 return NT_STATUS_OK; 143} 144 145static uint16_t dcesrv_echo_TestDoublePointer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestDoublePointer *r) 146{ 147 if (!*r->in.data) 148 return 0; 149 if (!**r->in.data) 150 return 0; 151 return ***r->in.data; 152} 153 154struct echo_TestSleep_private { 155 struct dcesrv_call_state *dce_call; 156 struct echo_TestSleep *r; 157}; 158 159static void echo_TestSleep_handler(struct tevent_context *ev, struct tevent_timer *te, 160 struct timeval t, void *private_data) 161{ 162 struct echo_TestSleep_private *p = talloc_get_type(private_data, 163 struct echo_TestSleep_private); 164 struct echo_TestSleep *r = p->r; 165 NTSTATUS status; 166 167 r->out.result = r->in.seconds; 168 169 status = dcesrv_reply(p->dce_call); 170 if (!NT_STATUS_IS_OK(status)) { 171 DEBUG(0,("echo_TestSleep_handler: dcesrv_reply() failed - %s\n", 172 nt_errstr(status))); 173 } 174} 175 176static long dcesrv_echo_TestSleep(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct echo_TestSleep *r) 177{ 178 struct echo_TestSleep_private *p; 179 180 if (!(dce_call->state_flags & DCESRV_CALL_STATE_FLAG_MAY_ASYNC)) { 181 /* we're not allowed to reply async */ 182 sleep(r->in.seconds); 183 return r->in.seconds; 184 } 185 186 /* we're allowed to reply async */ 187 p = talloc(mem_ctx, struct echo_TestSleep_private); 188 if (!p) { 189 return 0; 190 } 191 192 p->dce_call = dce_call; 193 p->r = r; 194 195 event_add_timed(dce_call->event_ctx, p, 196 timeval_add(&dce_call->time, r->in.seconds, 0), 197 echo_TestSleep_handler, p); 198 199 dce_call->state_flags |= DCESRV_CALL_STATE_FLAG_ASYNC; 200 return 0; 201} 202 203/* include the generated boilerplate */ 204#include "librpc/gen_ndr/ndr_echo_s.c" 205