1294336Sdes/* $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" 39294332Sdes#include "ssherr.h" 4060573Skris 41294332Sdesint 42294332Sdesdispatch_protocol_error(int type, u_int32_t seq, void *ctx) 43294332Sdes{ 44294332Sdes struct ssh *ssh = active_state; /* XXX */ 45294332Sdes int r; 4660573Skris 47124208Sdes logit("dispatch_protocol_error: type %d seq %u", type, seq); 4892555Sdes if (!compat20) 4992555Sdes fatal("protocol error"); 50294332Sdes if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 || 51294332Sdes (r = sshpkt_put_u32(ssh, seq)) != 0 || 52294332Sdes (r = sshpkt_send(ssh)) != 0 || 53294332Sdes (r = ssh_packet_write_wait(ssh)) != 0) 54294332Sdes sshpkt_fatal(ssh, __func__, r); 55294332Sdes return 0; 5660573Skris} 57294332Sdes 58294332Sdesint 59294332Sdesdispatch_protocol_ignore(int type, u_int32_t seq, void *ssh) 6092555Sdes{ 61124208Sdes logit("dispatch_protocol_ignore: type %d seq %u", type, seq); 62294332Sdes return 0; 6392555Sdes} 64294332Sdes 6592555Sdesvoid 66294332Sdesssh_dispatch_init(struct ssh *ssh, dispatch_fn *dflt) 6760573Skris{ 6892555Sdes u_int i; 6960573Skris for (i = 0; i < DISPATCH_MAX; i++) 70294332Sdes ssh->dispatch[i] = dflt; 7160573Skris} 72294332Sdes 7360573Skrisvoid 74294332Sdesssh_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; 81294332Sdes ssh->dispatch[i] = fn; 8292555Sdes } 8392555Sdes} 84294332Sdes 8592555Sdesvoid 86294332Sdesssh_dispatch_set(struct ssh *ssh, int type, dispatch_fn *fn) 8760573Skris{ 88294332Sdes ssh->dispatch[type] = fn; 8960573Skris} 90294332Sdes 91294332Sdesint 92294332Sdesssh_dispatch_run(struct ssh *ssh, int mode, volatile sig_atomic_t *done, 93294332Sdes void *ctxt) 9460573Skris{ 95294332Sdes int r; 96294332Sdes u_char type; 97294332Sdes u_int32_t seqnr; 98294332Sdes 9960573Skris for (;;) { 10060573Skris if (mode == DISPATCH_BLOCK) { 101294332Sdes r = ssh_packet_read_seqnr(ssh, &type, &seqnr); 102294332Sdes if (r != 0) 103294332Sdes return r; 10460573Skris } else { 105294332Sdes r = ssh_packet_read_poll_seqnr(ssh, &type, &seqnr); 106294332Sdes if (r != 0) 107294332Sdes return r; 10860573Skris if (type == SSH_MSG_NONE) 109294332Sdes return 0; 11060573Skris } 111294332Sdes if (type > 0 && type < DISPATCH_MAX && 112294332Sdes ssh->dispatch[type] != NULL) { 113294332Sdes if (ssh->dispatch_skip_packets) { 114294332Sdes debug2("skipped packet (type %u)", type); 115294332Sdes ssh->dispatch_skip_packets--; 116294332Sdes continue; 117294332Sdes } 118294332Sdes /* XXX 'ssh' will replace 'ctxt' later */ 119294332Sdes r = (*ssh->dispatch[type])(type, seqnr, ctxt); 120294332Sdes if (r != 0) 121294332Sdes return r; 122294332Sdes } else { 123294332Sdes r = sshpkt_disconnect(ssh, 124294332Sdes "protocol error: rcvd type %d", type); 125294332Sdes if (r != 0) 126294332Sdes return r; 127294332Sdes return SSH_ERR_DISCONNECTED; 128294332Sdes } 12960573Skris if (done != NULL && *done) 130294332Sdes return 0; 13160573Skris } 13260573Skris} 133294332Sdes 134294332Sdesvoid 135294332Sdesssh_dispatch_run_fatal(struct ssh *ssh, int mode, volatile sig_atomic_t *done, 136294332Sdes void *ctxt) 137294332Sdes{ 138294332Sdes int r; 139294332Sdes 140294336Sdes if ((r = ssh_dispatch_run(ssh, mode, done, ctxt)) != 0) 141294336Sdes sshpkt_fatal(ssh, __func__, r); 142294332Sdes} 143