1295367Sdes/* $OpenBSD: dispatch.c,v 1.27 2015/05/01 07:10:01 djm Exp $ */ 260573Skris/* 360573Skris * Copyright (c) 2000 Markus Friedl. All rights reserved. 460573Skris * 560573Skris * Redistribution and use in source and binary forms, with or without 660573Skris * modification, are permitted provided that the following conditions 760573Skris * are met: 860573Skris * 1. Redistributions of source code must retain the above copyright 960573Skris * notice, this list of conditions and the following disclaimer. 1060573Skris * 2. Redistributions in binary form must reproduce the above copyright 1160573Skris * notice, this list of conditions and the following disclaimer in the 1260573Skris * documentation and/or other materials provided with the distribution. 1360573Skris * 1460573Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1560573Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1660573Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1760573Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1860573Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1960573Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2060573Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2160573Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2260573Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2360573Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2460573Skris */ 25162852Sdes 2660573Skris#include "includes.h" 2776259Sgreen 28162852Sdes#include <sys/types.h> 29162852Sdes 30162852Sdes#include <signal.h> 31162852Sdes#include <stdarg.h> 32162852Sdes 3376259Sgreen#include "ssh1.h" 3476259Sgreen#include "ssh2.h" 3576259Sgreen#include "log.h" 3660573Skris#include "dispatch.h" 3760573Skris#include "packet.h" 3876259Sgreen#include "compat.h" 39295367Sdes#include "ssherr.h" 4060573Skris 41295367Sdesint 42295367Sdesdispatch_protocol_error(int type, u_int32_t seq, void *ctx) 43295367Sdes{ 44295367Sdes struct ssh *ssh = active_state; /* XXX */ 45295367Sdes int r; 4660573Skris 47124208Sdes logit("dispatch_protocol_error: type %d seq %u", type, seq); 4892555Sdes if (!compat20) 4992555Sdes fatal("protocol error"); 50295367Sdes if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || 51295367Sdes (r = sshpkt_put_u32(ssh, seq)) != 0 || 52295367Sdes (r = sshpkt_send(ssh)) != 0 || 53295367Sdes (r = ssh_packet_write_wait(ssh)) != 0) 54295367Sdes sshpkt_fatal(ssh, __func__, r); 55295367Sdes return 0; 5660573Skris} 57295367Sdes 58295367Sdesint 59295367Sdesdispatch_protocol_ignore(int type, u_int32_t seq, void *ssh) 6092555Sdes{ 61124208Sdes logit("dispatch_protocol_ignore: type %d seq %u", type, seq); 62295367Sdes return 0; 6392555Sdes} 64295367Sdes 6592555Sdesvoid 66295367Sdesssh_dispatch_init(struct ssh *ssh, dispatch_fn *dflt) 6760573Skris{ 6892555Sdes u_int i; 6960573Skris for (i = 0; i < DISPATCH_MAX; i++) 70295367Sdes ssh->dispatch[i] = dflt; 7160573Skris} 72295367Sdes 7360573Skrisvoid 74295367Sdesssh_dispatch_range(struct ssh *ssh, u_int from, u_int to, dispatch_fn *fn) 7592555Sdes{ 7692555Sdes u_int i; 7792555Sdes 7892555Sdes for (i = from; i <= to; i++) { 7992555Sdes if (i >= DISPATCH_MAX) 8092555Sdes break; 81295367Sdes ssh->dispatch[i] = fn; 8292555Sdes } 8392555Sdes} 84295367Sdes 8592555Sdesvoid 86295367Sdesssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn) 8760573Skris{ 88295367Sdes ssh->dispatch[type] = fn; 8960573Skris} 90295367Sdes 91295367Sdesint 92295367Sdesssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, 93295367Sdes void *ctxt) 9460573Skris{ 95295367Sdes int r; 96295367Sdes u_char type; 97295367Sdes u_int32_t seqnr; 98295367Sdes 9960573Skris for (;;) { 10060573Skris if (mode == DISPATCH_BLOCK) { 101295367Sdes r = ssh_packet_read_seqnr(ssh, &type, &seqnr); 102295367Sdes if (r != 0) 103295367Sdes return r; 10460573Skris } else { 105295367Sdes r = ssh_packet_read_poll_seqnr(ssh, &type, &seqnr); 106295367Sdes if (r != 0) 107295367Sdes return r; 10860573Skris if (type == SSH_MSG_NONE) 109295367Sdes return 0; 11060573Skris } 111295367Sdes if (type > 0 && type < DISPATCH_MAX && 112295367Sdes ssh->dispatch[type] != NULL) { 113295367Sdes if (ssh->dispatch_skip_packets) { 114295367Sdes debug2("skipped packet (type %u)", type); 115295367Sdes ssh->dispatch_skip_packets--; 116295367Sdes continue; 117295367Sdes } 118295367Sdes /* XXX 'ssh' will replace 'ctxt' later */ 119295367Sdes r = (*ssh->dispatch[type])(type, seqnr, ctxt); 120295367Sdes if (r != 0) 121295367Sdes return r; 122295367Sdes } else { 123295367Sdes r = sshpkt_disconnect(ssh, 124295367Sdes "protocol error: rcvd type %d", type); 125295367Sdes if (r != 0) 126295367Sdes return r; 127295367Sdes return SSH_ERR_DISCONNECTED; 128295367Sdes } 12960573Skris if (done != NULL && *done) 130295367Sdes return 0; 13160573Skris } 13260573Skris} 133295367Sdes 134295367Sdesvoid 135295367Sdesssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done, 136295367Sdes void *ctxt) 137295367Sdes{ 138295367Sdes int r; 139295367Sdes 140295367Sdes if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0) 141295367Sdes sshpkt_fatal(ssh, __func__, r); 142295367Sdes} 143