/* Handle channel specific requests, passing off to corresponding handlers * such as chansession or x11fwd */ void recv_msg_channel_request() { unsigned int chan; struct Channel *channel; TRACE(("enter recv_msg_channel_request")); chan = buf_getint(ses.payload); channel = getchannel(chan); if (channel == NULL) { /* disconnect ? */ dropbear_exit("Unknown channel"); } TRACE(("chan type is %d", channel->type)); /* handle according to channel type */ switch (channel->type) { case CHANNEL_ID_SESSION: TRACE(("continue recv_msg_channel_request: session request")); chansessionrequest(channel); break; default: send_msg_channel_failure(channel); } TRACE(("leave recv_msg_channel_request")); }
/* handle the channel EOF event, by closing the channel filedescriptor. The * channel isn't closed yet, it is left until the incoming (from the program * etc) FD is also EOF */ void recv_msg_channel_eof() { unsigned int chan; struct Channel * channel; TRACE(("enter recv_msg_channel_eof")); chan = buf_getint(ses.payload); channel = getchannel(chan); if (channel == NULL) { dropbear_exit("EOF for unknown channel"); } channel->recveof = 1; /* we should close the channel */ if (channel->type == CHANNEL_ID_X11 || channel->type == CHANNEL_ID_AGENT || channel->type == CHANNEL_ID_TCPDIRECT) { shutdown(channel->infd, 0); } else { close(channel->infd); } channel->infd = -1; if (channel->transeof && (channel->erreof || channel->errfd == -1) && !channel->sentclosed) { send_msg_channel_close(channel); } TRACE(("leave recv_msg_channel_eof")); }
/* Notification that our channel open request failed */ void recv_msg_channel_open_failure() { unsigned int chan; struct Channel * channel; chan = buf_getbyte(ses.payload); channel = getchannel(chan); if (channel == NULL) { dropbear_exit("Unknown channel"); } closechannel(channel); }
void ar5212DfsFound(struct ath_hal *ah, HAL_CHANNEL *chan, u_int64_t nolTime) { HAL_CHANNEL_INTERNAL *ichan; ichan = getchannel(ah, chan); if (ichan == AH_NULL) return; if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) ichan->dfs_tsf = ar5212GetTsf64(ah); ichan->dfs_tsf += nolTime; ichan->priv_flags |= CHANNEL_INTERFERENCE; chan->priv_flags |= CHANNEL_INTERFERENCE; }
/* * This function marks the channel as having found a dfs event * It also marks the end time that the dfs event should be cleared * If the channel is already marked, then tsf end time can only * be increased */ void ar9300_dfs_found(struct ath_hal *ah, HAL_CHANNEL *chan, u_int64_t nol_time) { HAL_CHANNEL_INTERNAL *ichan; ichan = getchannel(ah, chan); if (ichan == AH_NULL) { return; } if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) { ichan->dfs_tsf = ar9300_get_tsf64(ah); } ichan->dfs_tsf += nol_time; ichan->priv_flags |= CHANNEL_INTERFERENCE; chan->priv_flags |= CHANNEL_INTERFERENCE; }
/* * Check the internal channel list to see if the desired channel * is ok to release from the NOL. If not, then do nothing. If so, * mark the channel as clear and reset the internal tsf time */ void ar9300_check_dfs(struct ath_hal *ah, HAL_CHANNEL *chan) { HAL_CHANNEL_INTERNAL *ichan = AH_NULL; ichan = getchannel(ah, chan); if (ichan == AH_NULL) { return; } if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) { return; } ichan->priv_flags &= ~CHANNEL_INTERFERENCE; ichan->dfs_tsf = 0; }
/* when we receive channel data, put it in a buffer for writing to the program/ * shell etc */ void recv_msg_channel_data() { unsigned int chan; struct Channel * channel; unsigned int datalen; unsigned int pos; unsigned int maxdata; TRACE(("enter recv_msg_channel_data")); chan = buf_getint(ses.payload); channel = getchannel(chan); if (channel == NULL) { /* disconnect ? */ dropbear_exit("Unknown channel"); } assert(channel->infd != -1); datalen = buf_getint(ses.payload); /* if the client is going to send us more data than we've allocated, then * it has ignored the windowsize, so we "MAY ignore all extra data" */ maxdata = channel->writebuf->size - channel->writebuf->pos; if (datalen > maxdata) { TRACE(("Warning: recv_msg_channel_data: extra data past window")); datalen = maxdata; } /* write to the buffer - we always append to the end of the buffer */ pos = channel->writebuf->pos; buf_setpos(channel->writebuf, channel->writebuf->len); memcpy(buf_getwriteptr(channel->writebuf, datalen), buf_getptr(ses.payload, datalen), datalen); buf_incrwritepos(channel->writebuf, datalen); buf_setpos(channel->writebuf, pos); /* revert pos */ channel->recvwindow -= datalen; /* if (channel->recvwindow < RECV_MINWINDOW) { send_msg_channel_window_adjust(channel, RECV_MAXWINDOW - channel->recvwindow); channel->recvwindow = RECV_MAXWINDOW; }*/ TRACE(("leave recv_msg_channel_data")); }
void ar5212CheckDfs(struct ath_hal *ah, HAL_CHANNEL *chan) { HAL_CHANNEL_INTERNAL *ichan=AH_NULL; u_int64_t tsf; ichan = getchannel(ah, chan); if (ichan == AH_NULL) return; if (!(ichan->priv_flags & CHANNEL_INTERFERENCE)) return; tsf = ar5212GetTsf64(ah); if (tsf >= ichan->dfs_tsf) { ichan->priv_flags &= ~CHANNEL_INTERFERENCE; ichan->dfs_tsf = 0; chan->priv_flags &= ~CHANNEL_INTERFERENCE; } }
/* Confirmation that our channel open request (for forwardings) was * successful*/ void recv_msg_channel_open_confirmation() { unsigned int chan; struct Channel * channel; TRACE(("enter recv_msg_channel_open_confirmation")); chan = buf_getint(ses.payload); channel = getchannel(chan); if (channel == NULL) { dropbear_exit("Unknown channel"); } channel->remotechan = buf_getint(ses.payload); channel->transwindow = buf_getint(ses.payload); channel->transmaxpacket = buf_getint(ses.payload); TRACE(("leave recv_msg_channel_open_confirmation")); }
/* Increment the outgoing data window for a channel - the remote end limits * the amount of data which may be transmitted, this window is decremented * as data is sent, and incremented upon receiving window-adjust messages */ void recv_msg_channel_window_adjust() { unsigned int chan; struct Channel * channel; unsigned int incr; chan = buf_getint(ses.payload); channel = getchannel(chan); if (channel == NULL) { dropbear_exit("Unknown channel"); /* TODO - disconnect */ } incr = buf_getint(ses.payload); TRACE(("received window increment %d", incr)); incr = MIN(incr, MAX_TRANS_WIN_INCR); channel->transwindow += incr; channel->transwindow = MIN(channel->transwindow, MAX_TRANS_WINDOW); }
/* Handle channel closure(), respond in kind and close the channels */ void recv_msg_channel_close() { unsigned int chan; struct Channel * channel; TRACE(("enter recv_msg_channel_close")); chan = buf_getint(ses.payload); TRACE(("close channel = %d", chan)); channel = getchannel(chan); if (channel == NULL) { /* disconnect ? */ dropbear_exit("Close for unknown channel"); } if (!channel->sentclosed) { send_msg_channel_close(channel); } closechannel(channel); TRACE(("leave recv_msg_channel_close")); }