Beispiel #1
0
/*
 * Handle initial connection protocol.
 */
static int tftp(struct testcase *test, struct tftphdr *tp, int size)
{
  char *cp;
  int first = 1, ecode;
  struct formats *pf;
  char *filename, *mode = NULL;

  /* store input protocol */
  fprintf(test->server, "opcode: %x\n", tp->th_opcode);

  cp = (char *)&tp->th_stuff;
  filename = cp;
again:
  while (cp < buf + size) {
    if (*cp == '\0')
      break;
    cp++;
  }
  if (*cp) {
    nak(EBADOP);
    return 3;
  }
  if (first) {
    mode = ++cp;
    first = 0;
    goto again;
  }
  /* store input protocol */
  fprintf(test->server, "filename: %s\n", filename);

  for (cp = mode; *cp; cp++)
    if (isupper((int)*cp))
      *cp = tolower((int)*cp);

  /* store input protocol */
  fprintf(test->server, "mode: %s\n", mode);

  for (pf = formats; pf->f_mode; pf++)
    if (strcmp(pf->f_mode, mode) == 0)
      break;
  if (!pf->f_mode) {
    nak(EBADOP);
    return 2;
  }
  ecode = validate_access(test, filename, tp->th_opcode);
  if (ecode) {
    nak(ecode);
    return 1;
  }
  if (tp->th_opcode == WRQ)
    recvtftp(test, pf);
  else
    sendtftp(test, pf);

  return 0;
}
void FstopComms::respondWrite()
{
    if(!checkcheck())
        return;

    unsigned int addr=getAddr();
    char len=cmd[PKT_LEN];

    if(len < 1 || len > PKT_MAXREQ || addr < EEPROM_MIN_WRITE || addr+len > EEPROM_MAX_WRITE){
        nak(BAD_WRITE);
        return;
    }

    // copy from buffer to EEPROM
    char bp=PKT_SHORTHDR;
    for(char i=0;i<len;++i){
        EEPROM.write(addr++, cmd[bp++]);
    }

    cmd[PKT_CMD]=COM_WRITEACK;
    buflen=PKT_SHORTHDR;

    // recompute checksum, send without data
    txCmd();
}
void tftpd_general(void *p_info, int socket_ID)
{
    connect_info_S *p_con_info=(connect_info_S *)p_info;
    FILE *f;
    int result=255;

    if (p_con_info->job==RRQ)
    {
        f=fopen(p_con_info->p_name,"rb");
        if(f == NULL)
        {
            nak(socket_ID, &p_con_info->adresse, errno,strerror(errno));
            tftp_free(p_con_info->p_name);
            tftp_free(p_con_info);
            close(socket_ID);
            return ;
        }
        result=tftp_send(&p_con_info->adresse,p_con_info->p_name,"octet",0,TFTPsread,f);
        fclose(f);
    }
    else if (p_con_info->job==WRQ)
    {
        result=tftp_receive(&p_con_info->adresse,p_con_info->p_name,"octet",0,TFTPswrite,f);
    }
    else
    {
        DEBUG_MSG("TFTP op code is not correct \n");
    }

    if (result!=0) DEBUG_MSG("TFTP error\n");
    tftp_free(p_con_info->p_name);
    tftp_free(p_con_info);
    return ;
}
/**
 * The client is requesting an offer.
 *
 * @returns true.
 *
 * @param   pDhcpMsg    The message.
 * @param   cb          The message size.
 */
bool NetworkManager::handleDhcpReqRequest(PCRTNETBOOTP pDhcpMsg, size_t cb)
{
    ConfigurationManager *confManager = ConfigurationManager::getConfigurationManager();

    /* 1. find client */
    Client client = confManager->getClientByDhcpPacket(pDhcpMsg, cb);

    /* 2. find bound lease */
    Lease l = client.lease();
    if (l != Lease::NullLease)
    {

        if (l.isExpired())
        {
            /* send client to INIT state */
            Client c(client);
            nak(client, pDhcpMsg->bp_xid);
            confManager->expireLease4Client(c);
            return true;
        }
        else {
            /* XXX: Validate request */
            RawOption opt;
            RT_ZERO(opt);

            Client c(client);
            int rc = confManager->commitLease4Client(c);
            AssertRCReturn(rc, false);

            rc = ConfigurationManager::extractRequestList(pDhcpMsg, cb, opt);
            AssertRCReturn(rc, false);

            ack(client, pDhcpMsg->bp_xid, opt.au8RawOpt, opt.cbRawOpt);
        }
    }
    else
    {
        nak(client, pDhcpMsg->bp_xid);
    }
    return true;
}
DhcpServerMessage *DHCPD::doRequest(DhcpClientMessage &req)
{
    OptRequestedAddress reqAddr(req);
    if (req.ciaddr().u != 0 && reqAddr.present() && reqAddr.value().u != req.ciaddr().u)
    {
        std::unique_ptr<DhcpServerMessage> nak (
            createMessage(RTNET_DHCP_MT_NAC, req)
        );
        nak->addOption(OptMessage("Requested address does not match ciaddr"));
        return nak.release();
    }


    Binding *b = m_db.allocateBinding(req);
    if (b == NULL)
    {
        return createMessage(RTNET_DHCP_MT_NAC, req);
    }


    std::unique_ptr<DhcpServerMessage> ack (
        createMessage(RTNET_DHCP_MT_ACK, req)
    );

    b->setState(Binding::ACKED);
    saveLeases();

    ack->setYiaddr(b->addr());
    ack->addOption(OptLeaseTime(b->leaseTime()));

    OptParameterRequest optlist(req);
    ack->addOptions(m_pConfig->getOptions(optlist, req.clientId()));

    ack->addOption(OptMessage("Ok, ok, here it is"));

    ack->maybeUnicast(req);
    return ack.release();
}
int tftp_connection(struct sockaddr_in _adresse, short _job, char *_name, int socket_ID)
{

    char *p_copy_buf=_name;
    connect_info_S *p_con_info;
    int pid;

    printf("tftp_connection\n");
    while ((p_copy_buf<_name+SEGSIZE-5)&&(*p_copy_buf!=' ')&&(*p_copy_buf!='\0')) p_copy_buf++;
    /* Corrupt packet - no final NULL */
    if ((*p_copy_buf!= ' ')&&(*p_copy_buf!='\0'))
    {
        DEBUG_MSG("file name is corrupted. \n");
        nak(socket_ID, &_adresse, (int)EBADOP,strerror(EBADOP));
        close(socket_ID);
        return 255;
    };
    *p_copy_buf='\0';
    p_con_info=(connect_info_S*)malloc(sizeof(connect_info_S));
    p_con_info->p_name=(char*)malloc(p_copy_buf-_name+1);
    strcpy(p_con_info->p_name,_name);
    p_con_info->adresse=_adresse;
    p_con_info->job=_job;

    pid = fork();
    if(pid < 0)
        printf("TFTP fork error");
    else if(pid == 0)    //child process
    {
        tftpd_general(p_con_info, socket_ID);
        exit(0);
    }
    else                    //parent process
        ;

    return 0;
}
void FstopComms::respondRead()
{
    if(!checkcheck())
        return;

    unsigned int addr=getAddr();
    char len=cmd[PKT_LEN];

    if(len < 1 || len > PKT_MAXREQ || addr < EEPROM_MIN_READ || addr+len > EEPROM_MAX_READ){
        nak(BAD_READ);
        return;
    }

    // read from EEPROM into buffer
    cmd[PKT_CMD]=COM_READACK;

    for(char i=0;i<len;++i){
        cmd[i+PKT_SHORTHDR]=EEPROM.read(addr++);
    }
    buflen=len+PKT_SHORTHDR;

    // append checksum and send.
    txCmd();
}
Beispiel #8
0
  void Acknowledge::
  track_queue (Address const& addr, Queue& q, Messages& msgs)
  {
    unsigned short max_payload_size (
      params_.max_packet_size () - max_service_size);

    u32 max_elem (NAK::max_count (max_payload_size));
    u32 count (0);

    Queue::iterator i (q.begin ()), e (q.end ());

    // Track existing losses.
    //
    while (i != e)
    {
      auto_ptr<NAK> nak (new NAK (addr));

      // Inner loop that fills NAK profile with up to max_elem elements.
      //
      for (; i != e && nak->count () < max_elem; ++i)
      {
        u64 sn ((*i).ext_id_);
        Descr& d = (*i).int_id_;

        if (d.lost ())
        {
          d.timer (d.timer () - 1);

          if (d.timer () == 0)
          {
            //@@ Need exp fallback.
            //
            d.nak_count (d.nak_count () + 1);
            d.timer ((d.nak_count () + 1) * params_.nak_timeout ());

            nak->add (sn);

            ++count;

            // cerr << 6 << "NAK # " << d.nak_count () << ": "
            // << addr << " " << sn << endl;
          }
        }
      }

      // Send this NAK.
      //
      if (nak->count ())
      {
        // cerr << 5 << "NAK: " << addr << " " << nak->count () << " sns"
        //     << endl;

        Message_ptr m (new Message);

        m->add (Profile_ptr (nak.release ()));

        msgs.push_back (m);
      }
    }

    // Detect and record new losses.
    //
    for (u64 sn (q.sn () + 1), end (q.max_sn ()); sn < end; ++sn)
    {
      if (q.find (sn) == -1)
      {
        q.bind (sn, Descr (1));
      }
    }
  }
Beispiel #9
0
/*
 * Handle initial connection protocol.
 */
void
tftp(struct tftphdr *tp, int size)
{
	char *cp;
	size_t i;
	int first = 1, has_options = 0, ecode;
	struct formats *pf;
	char *filename, *mode = NULL, *option, *ccp;
	char fnbuf[MAXPATHLEN];

	cp = tp->th_stuff;
again:
	while (cp < buf + size) {
		if (*cp == '\0')
			break;
		cp++;
	}
	if (*cp != '\0') {
		nak(EBADOP);
		exit(1);
	}
	i = cp - tp->th_stuff;
	if (i >= sizeof(fnbuf)) {
		nak(EBADOP);
		exit(1);
	}
	memcpy(fnbuf, tp->th_stuff, i);
	fnbuf[i] = '\0';
	filename = fnbuf;
	if (first) {
		mode = ++cp;
		first = 0;
		goto again;
	}
	for (cp = mode; *cp; cp++)
		if (isupper(*cp))
			*cp = tolower(*cp);
	for (pf = formats; pf->f_mode; pf++)
		if (strcmp(pf->f_mode, mode) == 0)
			break;
	if (pf->f_mode == NULL) {
		nak(EBADOP);
		exit(1);
	}
	while (++cp < buf + size) {
		for (i = 2, ccp = cp; i > 0; ccp++) {
			if (ccp >= buf + size) {
				/*
				 * Don't reject the request, just stop trying
				 * to parse the option and get on with it.
				 * Some Apple OpenFirmware versions have
				 * trailing garbage on the end of otherwise
				 * valid requests.
				 */
				goto option_fail;
			} else if (*ccp == '\0')
				i--;
		}
		for (option = cp; *cp; cp++)
			if (isupper(*cp))
				*cp = tolower(*cp);
		for (i = 0; options[i].o_type != NULL; i++)
			if (strcmp(option, options[i].o_type) == 0) {
				options[i].o_request = ++cp;
				has_options = 1;
			}
		cp = ccp-1;
	}

option_fail:
	if (options[OPT_TIMEOUT].o_request) {
		int to = atoi(options[OPT_TIMEOUT].o_request);
		if (to < 1 || to > 255) {
			nak(EBADOP);
			exit(1);
		}
		else if (to <= max_rexmtval)
			options[OPT_TIMEOUT].o_reply = rexmtval = to;
		else
			options[OPT_TIMEOUT].o_request = NULL;
	}

	ecode = (*pf->f_validate)(&filename, tp->th_opcode);
	if (has_options)
		oack();
	if (logging) {
		char hbuf[NI_MAXHOST];

		getnameinfo((struct sockaddr *)&from, from.ss_len,
			    hbuf, sizeof(hbuf), NULL, 0, 
			    NI_WITHSCOPEID);
		syslog(LOG_INFO, "%s: %s request for %s: %s", hbuf,
			tp->th_opcode == WRQ ? "write" : "read",
			filename, errtomsg(ecode));
	}
	if (ecode) {
		/*
		 * Avoid storms of naks to a RRQ broadcast for a relative
		 * bootfile pathname from a diskless Sun.
		 */
		if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
			exit(0);
		nak(ecode);
		exit(1);
	}
	if (tp->th_opcode == WRQ)
		(*pf->f_recv)(pf);
	else
		(*pf->f_send)(pf);
	exit(0);
}
Beispiel #10
0
/* Send the requested file */
void my_sendfile( Client *cl ) {
	int oerrno;
	struct tftphdr *tp = cl->tp;
	int opcode, block, readblock;

	readblock = 0;
	if (tp != NULL) {
		/* Process an input packet */
		opcode = ntohs((u_short)tp->th_opcode);

		/* Give up if the other side wants to */
		if (opcode == ERROR) {
			stats.errorop++;
			my_syslog( MLOG_TFTP, "%s.%d ERROR",
			    inet_ntoa(cl->sin.sin_addr), cl->sin.sin_port);
			cl->proc = CP_DONE;
			return;
		}

		/* If we didn't get an ACK, blow him away */
		//if (opcode != ACK) {
		//	/* XXX this probably can't happen */
		//	my_syslog( MLOG_TFTP, "%s.%d expected ACK",
		//	    inet_ntoa(cl->sin.sin_addr), cl->sin.sin_port);
		//	nak( cl, ERROR );
		//	return;
		//}
		if (opcode == RRQ) {
			cl->state = ST_INIT;
		}

		if (cl->state == ST_WAITACK || cl->state == ST_LASTACK) {
			/* If he didn't ack the right block, ignore packet */
			block = ntohs((u_short)tp->th_block);
			if (block > cl->maxb) { nak( cl, ERROR ); return; }

			/* Check if we're done */
			if (cl->state == ST_LASTACK && block == cl->maxb) { cl->proc = CP_DONE; return; }

			if (block != cl->block) cl->block = block;

			/* Setup to send the next block */
			cl->block++;
			readblock++;
			cl->state = ST_SEND;
			cl->wakeup = 0;
			cl->retries = WAIT_RETRIES;
		}
	}

	/* See if it's time to resend */
	if (cl->wakeup != 0 && cl->wakeup <= now &&
	   (cl->state == ST_WAITACK || cl->state == ST_LASTACK)) {
		stats.retrans++;
		my_syslog( MLOG_TFTP, "%s retrans blk %d",
		    inet_ntoa(cl->sin.sin_addr), cl->block );
		cl->state = ST_SEND;
	}

	/* Initialize some stuff the first time through */
	if (cl->state == ST_INIT) {
		cl->block = 1;
		readblock++;
		cl->state = ST_SEND;
		cl->wakeup = 0;
		cl->retries = WAIT_RETRIES;
		cl->dp = NULL;
	}

	/* If our first time through or the last block was ack'ed, read */
	if (readblock) {
		errno = 0;
		if (read_block( cl->fnum, cl->block, &(cl->dp), (u_int32_t *) &(cl->dpcc) ) != 0) {
			stats.fileioerror++;
			nak( cl, errno + 100 );
			return;
		}

		/* Bail if we run into trouble */
		if (cl->dpcc < 0) {
			stats.fileioerror++;
			nak( cl, errno + 100 );
			return;
		}
	}

	if (cl->state == ST_SEND) {
		/* See if it's time to give up on this turkey */
		cl->retries--;
		if (cl->retries < 0) {
			stats.timeout++;
			my_syslog( MLOG_TFTP, "%s timeout blk %d",
			    inet_ntoa(cl->sin.sin_addr), cl->block );
			cl->proc = CP_DONE;
			return;
		}

		/* Send the block */
		if (sendto(tftp_socket, (char *)cl->dp, cl->dpcc, 0,
		    (struct sockaddr *)&cl->sin, sizeof(cl->sin)) != cl->dpcc) {
			oerrno = errno;
			my_syslog( MLOG_TFTP, "sendfile: write: %m");
			nak( cl, oerrno + 100 );
			return;
		}
		stats.sent++;

		/*	log(LOG_DEBUG, "%s.%d > %d",
			    inet_ntoa(cl->sin.sin_addr),
			    cl->sin.sin_port,
			    cl->block);
		*/

		if (cl->dpcc == (SEGSIZE + 4))
			cl->state = ST_WAITACK;
		else
			cl->state = ST_LASTACK;
		cl->wakeup = now + WAIT_TIMEOUT;
	}
}
Beispiel #11
0
/* Handle initial connection protocol  */
void tftp( Client *cl ) {
	struct tftphdr	*tp;
	char		*cp, *cp2, *ep;
	int		ecode;
	char		*mode;
	char		file[MAXPATHLEN];

	tp = cl->tp;
	tp->th_opcode = ntohs((u_short)tp->th_opcode);
	if (tp->th_opcode != RRQ) {
		// nak( cl, EBADOP );
		return;
	}

	errstr = NULL;
	cp = (char *)&tp->th_block;
	ep = (char *)cl->tp + cl->tpcc;

	if ( (ep - cp) > MAXPATHLEN ) {
		stats.badfilename++;
		nak( cl, EBADOP );
		return;
	}

	if ( *cp == '/' ) { cp++; }

	/* Extract filename */
	cp2 = file;
	while (cp < ep && *cp != '\0')
		*cp2++ = *cp++;
	if (cp >= ep) {
		++stats.badfilename;
		nak(cl, EBADOP);
		return;
	}
	*cp2 = '\0';
	++cp;

	/* Make sure mode is in packet */
	mode = cp;
	while (cp < ep && *cp != '\0') cp++;
	if (cp >= ep) {
		stats.badfilemode++;
		nak( cl, EBADOP );
		return;
	}

	if (strcasecmp(mode, "octet") != 0) {
		stats.badfilemode++;
		nak( cl, EBADOP );
		return;
	}

	ecode = validate_access( cl, file );
	if (ecode) {
		my_syslog( MLOG_TFTP, "%s %s \"%s\" DENIED (%s)",
			inet_ntoa(cl->sin.sin_addr),
			tp->th_opcode == WRQ ? "write" : "read",
			file,
			errstr != NULL ? errstr : errtomsg(ecode));
		cl->proc = CP_DONE;
		return;
	}

	if (cl->dynam == 0)
		my_TFTPlog( file, cl->sin.sin_addr.s_addr );
	/* my_syslog( MLOG_TFTP, "%s-%s req for \"%s\" from %s",
	    tp->th_opcode == WRQ ? "write" : "read",
	    mode, file, inet_ntoa(cl->sin.sin_addr));
	*/

	cl->state = ST_INIT;
	cl->tp = NULL;
	cl->tpcc = 0;
	cl->proc = CP_SENDFILE;
	// sendfile( cl );
}
Beispiel #12
0
/*
 * Receive a file.
 */
void
recvfile(struct formats *pf)
{
	struct tftphdr *dp;
	struct tftphdr *ap;    /* ack buffer */
	int n, size;
	volatile unsigned short block;

	signal(SIGALRM, timer);
	dp = w_init();
	ap = (struct tftphdr *)ackbuf;
	block = 0;
	do {
		timeouts = 0;
		ap->th_opcode = htons((u_short)ACK);
		ap->th_block = htons((u_short)block);
		block++;
		(void) setjmp(timeoutbuf);
send_ack:
		if (send(peer, ackbuf, 4, 0) != 4) {
			syslog(LOG_ERR, "write: %m");
			goto abort;
		}
		write_behind(file, pf->f_convert);
		for ( ; ; ) {
			alarm(rexmtval);
			n = recv(peer, dp, PKTSIZE, 0);
			alarm(0);
			if (n < 0) {            /* really? */
				syslog(LOG_ERR, "read: %m");
				goto abort;
			}
			dp->th_opcode = ntohs((u_short)dp->th_opcode);
			dp->th_block = ntohs((u_short)dp->th_block);
			if (dp->th_opcode == ERROR)
				goto abort;
			if (dp->th_opcode == DATA) {
				if (dp->th_block == block) {
					break;   /* normal */
				}
				/* Re-synchronize with the other side */
				(void) synchnet(peer);
				if (dp->th_block == (block-1))
					goto send_ack;          /* rexmit */
			}
		}
		/*  size = write(file, dp->th_data, n - 4); */
		size = writeit(file, &dp, n - 4, pf->f_convert);
		if (size != (n-4)) {                    /* ahem */
			if (size < 0) nak(errno + 100);
			else nak(ENOSPACE);
			goto abort;
		}
	} while (size == SEGSIZE);
	write_behind(file, pf->f_convert);
	(void) fclose(file);            /* close data file */

	ap->th_opcode = htons((u_short)ACK);    /* send the "final" ack */
	ap->th_block = htons((u_short)(block));
	(void) send(peer, ackbuf, 4, 0);

	signal(SIGALRM, justquit);      /* just quit on timeout */
	alarm(rexmtval);
	n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
	alarm(0);
	if (n >= 4 &&                   /* if read some data */
	    dp->th_opcode == DATA &&    /* and got a data block */
	    block == dp->th_block) {	/* then my last ack was lost */
		(void) send(peer, ackbuf, 4, 0);     /* resend final ack */
	}
abort:
	return;
}
Beispiel #13
0
static int ProcessMsg (SOCKET s, const struct S_ConsoleMsg *pmsg)
{
struct LL_TftpInfo *pTftp;
int                 uServices;

LogToMonitor ("TFTPd console receive msg %d\n", pmsg->type);
    switch (pmsg->type)
    {
        case C_CONS_KILL_TRF :
            LOG (1, "transfer %d must be killed", pmsg->u.kill.dwTransferId);
            for ( pTftp=pTftpFirst ; 
                  pTftp!=NULL && pTftp->tm.dwTransferId != pmsg->u.kill.dwTransferId ;
                  pTftp = pTftp->next );
			if (pTftp != NULL) { nak (pTftp, ECANCELLED); pTftp->st.ret_code=TFTP_TRF_STOPPED; }
            break;
            
        case C_TFTP_TERMINATE :
LogToMonitor ("terminating TFTP service\n");
            tThreads[TH_TFTP].gRunning = FALSE;
            WakeUpThread (TH_TFTP);
            break;
        
        case C_DHCP_TERMINATE :
LogToMonitor ("terminating DHCP service\n");
            tThreads[TH_DHCP].gRunning = FALSE;
            // wake up DHCP thread
	        WakeUpThread (TH_DHCP);
            break;
            
        case C_TERMINATE :
LogToMonitor ("stopping services\n");
            TerminateWorkerThreads (FALSE); // keep management threads
            break;  

        case C_SUSPEND :
LogToMonitor ("suspending services\n");
            TerminateWorkerThreads (TRUE); // keep management threads
            break;            
            
        case C_START :
LogToMonitor ("starting services\n");
			StartMultiWorkerThreads (TRUE);
            break;            
            
        case C_DHCP_RRQ_SETTINGS :
LogToMonitor ("sending DHCP settings\n");
            SendMsg (s, C_DHCP_RPLY_SETTINGS, & sParamDHCP, sizeof sParamDHCP);
            break;
            
        case C_TFTP_RRQ_SETTINGS :
LogToMonitor ("sending TFTP settings\n");
            SendMsg (s, C_TFTP_RPLY_SETTINGS, & sSettings, sizeof sSettings);
            break;
            
        case C_DHCP_WRQ_SETTINGS :
LogToMonitor ("storing new DHCP settings\n");
            DHCPSaveConfig ( & pmsg->u.dhcp_settings );
            break;
            
        case C_TFTP_WRQ_SETTINGS :
LogToMonitor ("storing new TFTP settings\n");
			{static struct S_RestartTable sRestart;
			    sRestart.newservices = pmsg->u.tftp_settings.uServices;
				sRestart.oldservices = sSettings.uServices;
				sRestart.flapservices = 0;
				if (   sSettings.Port != pmsg->u.tftp_settings.Port
		            || lstrcmp (sSettings.szTftpLocalIP, pmsg->u.tftp_settings.szTftpLocalIP )!=0 )
					sRestart.flapservices |= TFTPD32_TFTP_SERVER;
				// restart syslog if its settings log has changed
				if (     sSettings.uServices &  TFTPD32_SYSLOG_SERVER 
					  && (   sSettings.bSyslogPipe != pmsg->u.tftp_settings.bSyslogPipe
					      || strcmp(sSettings.szSyslogFile,pmsg->u.tftp_settings.szSyslogFile)!= 0 )
				   )
					 sRestart.flapservices |= TFTPD32_SYSLOG_SERVER;

            sSettings = pmsg->u.tftp_settings;

            if ( IsValidDirectory ( pmsg->u.tftp_settings.szBaseDirectory ) )
                    lstrcpyn ( sSettings.szWorkingDirectory, 
                               pmsg->u.tftp_settings.szBaseDirectory, 
                               sizeof sSettings.szWorkingDirectory );
			_beginthread ( Tftpd32UpdateServices, 0, (void *) & sRestart );            
			Tftpd32SaveSettings ();
			}
			break;

        case C_TFTP_RESTORE_DEFAULT_SETTINGS :
LogToMonitor ("restore default settings\n");
            Tftpd32DestroySettings ();
            break;
            
        case C_TFTP_CHG_WORKING_DIR :
LogToMonitor ("changing working directory to <%s>\n", pmsg->u.working_dir);
            if ( IsValidDirectory ( pmsg->u.working_dir ) )
                    lstrcpyn ( sSettings.szWorkingDirectory, 
                               pmsg->u.working_dir, 
                               sizeof sSettings.szWorkingDirectory );
            break;
        case C_RRQ_WORKING_DIR :
LogToMonitor ("sending working directory <%s>\n", sSettings.szWorkingDirectory);
            SendMsg (s, C_REPLY_WORKING_DIR, 
                     sSettings.szWorkingDirectory, 
                     1 + lstrlen (sSettings.szWorkingDirectory) );
            break;
        
        case C_DELETE_ASSIGNATION :
LogToMonitor ("deleting DHCP entry %X\n", pmsg->u.del_lease.ip);
            { struct in_addr  addr;
              BOOL   dummy;
                addr.s_addr = pmsg->u.del_lease.ip;
                DHCPDestroyItem ( DHCPSearchByIP ( & addr, &dummy  ) );
            }
            break;

		case C_RRQ_GET_SERVICES :
LogToMonitor ("sending running services\n");
			uServices = GetRunningThreads ();
            SendMsg (s, 
				     C_REPLY_GET_SERVICES, 
					 & uServices,
					 sizeof uServices );
            break;

		case C_RRQ_GET_INTERFACES :
LogToMonitor ("sending IP interfaces");
			AnswerIPList ();
			break;

        case C_RRQ_DIRECTORY_CONTENT :
LogToMonitor ("sending Directory content");
            SendDirectoryContent ();
            break;

        case C_TFTP_GET_FULL_STAT :
LogToMonitor ("sending Directory content");
            ConsoleTftpGetStatistics ();
            break;

		default :
LogToMonitor ("Service received unknown message %d\n", pmsg->type);
            break;

    }   
return 1;    
} // ReadMsg
Beispiel #14
0
/*
 * Send the requested file.
 */
static void sendtftp(struct testcase *test, struct formats *pf)
{
  struct tftphdr *dp;
  struct tftphdr *ap;    /* ack packet */
  unsigned short block = 1;
  int size, n;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  dp = r_init();
  ap = (struct tftphdr *)ackbuf;
  do {
    size = readit(test, &dp, pf->f_convert);
    if (size < 0) {
      nak(errno + 100);
      return;
    }
    dp->th_opcode = htons((u_short)DATA);
    dp->th_block = htons((u_short)block);
    timeout = 0;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
    send_data:
    if (send(peer, dp, size + 4, 0) != size + 4) {
      logmsg("write\n");
      return;
    }
    read_ahead(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);        /* read the ack */
#endif
      n = recv(peer, ackbuf, sizeof (ackbuf), 0);
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if (n < 0) {
        logmsg("read: fail\n");
        return;
      }
      ap->th_opcode = ntohs((u_short)ap->th_opcode);
      ap->th_block = ntohs((u_short)ap->th_block);

      if (ap->th_opcode == ERROR) {
        logmsg("got ERROR");
        return;
      }

      if (ap->th_opcode == ACK) {
        if (ap->th_block == block) {
          break;
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (ap->th_block == (block -1)) {
          goto send_data;
        }
      }

    }
    block++;
  } while (size == SEGSIZE);
}
Beispiel #15
0
/*
 * Send the requested file.
 */
static void sendtftp(struct testcase *test, struct formats *pf)
{
  int size;
  ssize_t n;
  sendblock = 1;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  sdp = r_init();
  sap = (struct tftphdr *)ackbuf;
  do {
    size = readit(test, &sdp, pf->f_convert);
    if (size < 0) {
      nak(ERRNO + 100);
      return;
    }
    sdp->th_opcode = htons((u_short)opcode_DATA);
    sdp->th_block = htons((u_short)sendblock);
    timeout = 0;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
    send_data:
    if (swrite(peer, sdp, size + 4) != size + 4) {
      logmsg("write");
      return;
    }
    read_ahead(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);        /* read the ack */
#endif
      n = sread(peer, ackbuf, sizeof (ackbuf));
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if (n < 0) {
        logmsg("read: fail");
        return;
      }
      sap->th_opcode = ntohs((u_short)sap->th_opcode);
      sap->th_block = ntohs((u_short)sap->th_block);

      if (sap->th_opcode == opcode_ERROR) {
        logmsg("got ERROR");
        return;
      }

      if (sap->th_opcode == opcode_ACK) {
        if (sap->th_block == sendblock) {
          break;
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (sap->th_block == (sendblock-1)) {
          goto send_data;
        }
      }

    }
    sendblock++;
  } while (size == SEGSIZE);
}
Beispiel #16
0
void
IPCP::RCREvent(struct mbuf *packet)
{
	TRACE("IPCP: RCREvent() state=%d\n", State());
	
	KPPPConfigurePacket request(packet);
	KPPPConfigurePacket nak(PPP_CONFIGURE_NAK);
	KPPPConfigurePacket reject(PPP_CONFIGURE_REJECT);
	
	// we should not use the same id as the peer
	if(fID == mtod(packet, ppp_lcp_packet*)->id)
		fID -= 128;
	
	nak.SetID(request.ID());
	reject.SetID(request.ID());
	
	// parse each item
	ppp_configure_item *item;
	in_addr_t *requestedAddress, *wishedAddress = NULL;
	for(int32 index = 0; index < request.CountItems(); index++) {
		item = request.ItemAt(index);
		if(!item)
			continue;
		
		// addresses have special handling to reduce code size
		switch(item->type) {
			case IPCP_ADDRESSES:
				// abandoned by the standard
			case IPCP_ADDRESS:
				wishedAddress = &fPeerRequests.address;
			break;
			
			case IPCP_PRIMARY_DNS:
				wishedAddress = &fPeerRequests.primaryDNS;
			break;
			
			case IPCP_SECONDARY_DNS:
				wishedAddress = &fPeerRequests.secondaryDNS;
			break;
		}
		
		// now parse item
		switch(item->type) {
			case IPCP_ADDRESSES:
				// abandoned by the standard
			case IPCP_ADDRESS:
			case IPCP_PRIMARY_DNS:
			case IPCP_SECONDARY_DNS:
				if(item->length != 6) {
					// the packet is invalid
					m_freem(packet);
					NewState(PPP_INITIAL_STATE);
					ReportUpFailedEvent();
					return;
				}
				
				requestedAddress = (in_addr_t*) item->data;
				if(*wishedAddress == INADDR_ANY) {
					if(*requestedAddress == INADDR_ANY) {
						// we do not have an address for you
						m_freem(packet);
						NewState(PPP_INITIAL_STATE);
						ReportUpFailedEvent();
						return;
					}
				} else if(*requestedAddress != *wishedAddress) {
					// we do not want this address
					ip_item ipItem;
					ipItem.type = item->type;
					ipItem.length = 6;
					ipItem.address = *wishedAddress;
					nak.AddItem((ppp_configure_item*) &ipItem);
				}
			break;
			
//			case IPCP_COMPRESSION_PROTOCOL:
				// TODO: implement me!
//			break;
			
			default:
				reject.AddItem(item);
		}
	}
	
	// append additional values to the nak
	if(!request.ItemWithType(IPCP_ADDRESS) && fPeerRequests.address == INADDR_ANY) {
		// The peer did not provide us his address. Tell him to do so.
		ip_item ipItem;
		ipItem.type = IPCP_ADDRESS;
		ipItem.length = 6;
		ipItem.address = INADDR_ANY;
		nak.AddItem((ppp_configure_item*) &ipItem);
	}
	
	if(nak.CountItems() > 0) {
		RCRBadEvent(nak.ToMbuf(Interface().MRU(), Interface().PacketOverhead()), NULL);
		m_freem(packet);
	} else if(reject.CountItems() > 0) {
		RCRBadEvent(NULL, reject.ToMbuf(Interface().MRU(),
			Interface().PacketOverhead()));
		m_freem(packet);
	} else
		RCRGoodEvent(packet);
}
/*
 * Handle initial connection protocol.
 */
int
tftp(struct tftphdr *tp, int size)
{
	char *cp;
	int argn, ecode;
	struct formats *pf = NULL;
	char *filename, *mode = NULL;

        char *val = NULL, *opt = NULL;
        char *ap = ackbuf + 2;

        ((struct tftphdr *)ackbuf)->th_opcode = ntohs(OACK);

	filename = cp = tp->th_stuff;
	// --> 2005/09/26 Ryan : using tmpfs for firmware upgrade to save run time memory
	printf("filename[%s]\n",filename);
	if (!strncmp(filename+5,"tmpfs",5))
	{
		mkdir("/tmp/tmpfs", 0777);
//TT		mount("tmpfs", "/tmp/tmpfs", "tmpfs", MS_MGC_VAL, NULL);
	}
	// <--

	argn = 0;

	while ( cp < buf + size && *cp ) {
	     do {
		  cp++;
	     } while (cp < buf + size && *cp);

	     if ( *cp ) {
		  nak(EBADOP);	/* Corrupt packet - no final NULL */
		  exit(0);
	     }

	     argn++;
	     if (argn == 1) {
		  mode = ++cp;
	     } else if (argn == 2) {
		  for (cp = mode; *cp; cp++)
			    *cp = tolower(*cp);
		  for (pf = formats; pf->f_mode; pf++) {
		       if (!strcmp(pf->f_mode, mode))
			    break;
		  }
		  if (!pf->f_mode) {
		       nak(EBADOP);
		       exit(0);
		  }
		  ecode = (*pf->f_validate)(filename, tp->th_opcode, pf);
		  if (ecode) {
		       nak(ecode);
		       exit(0);
		  }
		  opt = ++cp;
	     } else if ( argn & 1 ) {
		  val = ++cp;
	     } else {
		  do_opt(opt, val, &ap);
		  opt = ++cp;
	     }
	}

	if (!pf) {
	     nak(EBADOP);
	     exit(0);
	}

	if (strlen(filename) >= 128) {
	     nak(EBADOP);
	     exit(0);
	}
        strcpy(pf->filename, filename);

	//printf("tftp filename=%s\n",filename);
	if ( ap != (ackbuf+2) ) {
	     // doesn't come here
	     if ( tp->th_opcode == WRQ )
		  (*pf->f_recv)(pf, (struct tftphdr *)ackbuf, ap-ackbuf);
	     else
		  (*pf->f_send)(pf, (struct tftphdr *)ackbuf, ap-ackbuf);
	} else {
	     if (tp->th_opcode == WRQ)
		  (*pf->f_recv)(pf, NULL, 0);
	     else
		  (*pf->f_send)(pf, NULL, 0);
	}
	exit(1);
}
Beispiel #18
0
/*
 * Send the requested file.
 */
int tftp_sendfile(int f, union sock_addr *peeraddr,
		   int fd, const char *name, const char *mode)
{
    struct tftphdr *ap;         /* data and ack packets */
    struct tftphdr *dp;
    int n;
    volatile int is_request;
    volatile u_short block;
    volatile int size, convert;
    volatile off_t amount;
    union sock_addr from;
    socklen_t fromlen;
    FILE *file;
    u_short ap_opcode, ap_block;

    startclock();               /* start stat's clock */
    dp = r_init();              /* reset fillbuf/read-ahead code */
    ap = (struct tftphdr *)ackbuf;
    convert = !strcmp(mode, "netascii");
    file = fdopen(fd, convert ? "rt" : "rb");
    block = 0;
    is_request = 1;             /* First packet is the actual WRQ */
    amount = 0;

    bsd_signal(SIGALRM, timer);
    do {
        if (is_request) {
            size = makerequest(WRQ, name, dp, mode) - 4;
        } else {
            /*      size = read(fd, dp->th_data, SEGSIZE);   */
            size = readit(file, &dp, convert);
            if (size < 0) {
                nak(f, peeraddr, errno + 100, NULL);
                break;
            }
            dp->th_opcode = htons((u_short) DATA);
            dp->th_block = htons((u_short) block);
        }
        timeout = 0;
        (void)sigsetjmp(timeoutbuf, 1);

        if (trace)
            tpacket("sent", dp, size + 4);
        n = sendto(f, dp, size + 4, 0,
                   &(peeraddr->sa), SOCKLEN(peeraddr));
        if (n != size + 4) {
            perror("tftp: sendto");
            goto abort;
        }
        read_ahead(file, convert);
        for (;;) {
            alarm(rexmtval);
            do {
                fromlen = sizeof(from);
                n = recvfrom(f, ackbuf, sizeof(ackbuf), 0,
                             &from.sa, &fromlen);
            } while (n <= 0);
            alarm(0);
            if (n < 0) {
                perror("tftp: recvfrom");
                goto abort;
            }
            sa_set_port(peeraddr, SOCKPORT(&from));  /* added */
            if (trace)
                tpacket("received", ap, n);
            /* should verify packet came from server */
            ap_opcode = ntohs((u_short) ap->th_opcode);
            ap_block = ntohs((u_short) ap->th_block);
            if (ap_opcode == ERROR) {
                printf("Error code %d: %s\n", ap_block, ap->th_msg);
                goto abort;
            }
            if (ap_opcode == ACK) {
                int j;

                if (ap_block == block) {
                    break;
                }
                /* On an error, try to synchronize
                 * both sides.
                 */
                j = synchnet(f);
                if (j && trace) {
                    printf("discarded %d packets\n", j);
                }
                /*
                 * RFC1129/RFC1350: We MUST NOT re-send the DATA
                 * packet in response to an invalid ACK.  Doing so
                 * would cause the Sorcerer's Apprentice bug.
                 */
            }
        }
        if (!is_request)
            amount += size;
        is_request = 0;
        block++;
    } while (size == SEGSIZE || block == 1);
  abort:
    fclose(file);
    stopclock();
    //if (amount > 0)
    //    printstats("Sent", amount);
    return amount;
}
Beispiel #19
0
/*
 * Receive a file.
 */
int tftp_recvfile(int f, union sock_addr *peeraddr,
		   int fd, const char *name, const char *mode)
{
    struct tftphdr *ap;
    struct tftphdr *dp;
    int n;
    volatile u_short block;
    volatile int size, firsttrip;
    volatile unsigned long amount;
    union sock_addr from;
    socklen_t fromlen;
    FILE *file;
    volatile int convert;       /* true if converting crlf -> lf */
    u_short dp_opcode, dp_block;

    startclock();
    dp = w_init();
    ap = (struct tftphdr *)ackbuf;
    convert = !strcmp(mode, "netascii");
    file = fdopen(fd, convert ? "wt" : "wb");
    block = 1;
    firsttrip = 1;
    amount = 0;

    bsd_signal(SIGALRM, timer);
    do {
        if (firsttrip) {
            size = makerequest(RRQ, name, ap, mode);
            firsttrip = 0;
        } else {
            ap->th_opcode = htons((u_short) ACK);
            ap->th_block = htons((u_short) block);
            size = 4;
            block++;
        }
        timeout = 0;
        (void)sigsetjmp(timeoutbuf, 1);
      send_ack:
        if (trace)
            tpacket("sent", ap, size);
        if (sendto(f, ackbuf, size, 0, &(peeraddr->sa),
                   SOCKLEN(peeraddr)) != size) {
            alarm(0);
            perror("tftp: sendto");
            goto abort;
        }
        write_behind(file, convert);
        for (;;) {
            alarm(rexmtval);
            do {
                fromlen = sizeof(from);
                n = recvfrom(f, dp, PKTSIZE, 0,
                             &from.sa, &fromlen);
            } while (n <= 0);
            alarm(0);
            if (n < 0) {
                perror("tftp: recvfrom");
                goto abort;
            }
            sa_set_port(peeraddr, SOCKPORT(&from));  /* added */
            if (trace)
                tpacket("received", dp, n);
            /* should verify client address */
            dp_opcode = ntohs((u_short) dp->th_opcode);
            dp_block = ntohs((u_short) dp->th_block);
            if (dp_opcode == ERROR) {
                printf("Error code %d: %s\n", dp_block, dp->th_msg);
                goto abort;
            }
            if (dp_opcode == DATA) {
                int j;

                if (dp_block == block) {
                    break;      /* have next packet */
                }
                /* On an error, try to synchronize
                 * both sides.
                 */
                j = synchnet(f);
                if (j && trace) {
                    printf("discarded %d packets\n", j);
                }
                if (dp_block == (block - 1)) {
                    goto send_ack;      /* resend ack */
                }
            }
        }
        /*      size = write(fd, dp->th_data, n - 4); */
        size = writeit(file, &dp, n - 4, convert);
        if (size < 0) {
            nak(f, peeraddr, errno + 100, NULL);
            break;
        }
        amount += size;
    } while (size == SEGSIZE);
  abort:                       /* ok to ack, since user */
    ap->th_opcode = htons((u_short) ACK);       /* has seen err msg */
    ap->th_block = htons((u_short) block);
    (void)sendto(f, ackbuf, 4, 0, (struct sockaddr *)peeraddr,
                 SOCKLEN(peeraddr));
    write_behind(file, convert);        /* flush last buffer */
    fclose(file);
    stopclock();
    //if (amount > 0)
    //    printstats("Received", amount);
    return amount;
}
Beispiel #20
0
/*
 * Handle initial connection protocol.
 */
int tftp (struct tftphdr *tp, int size)
{
    char *cp;

    int argn, ecode;

    struct formats *pf = NULL;

    char *origfilename;

    char *filename, *mode = NULL;

    char *val = NULL, *opt = NULL;

    char *ap = ackbuf + 2;

    ((struct tftphdr *) ackbuf)->th_opcode = ntohs (OACK);

    origfilename = cp = (char *) &(tp->th_stuff);
    argn = 0;

    while (cp < buf + size && *cp)
    {
        do
        {
            cp++;
        }
        while (cp < buf + size && *cp);

        if (*cp)
        {
            nak (EBADOP);        /* Corrupt packet - no final NULL */
            exit (0);
        }

        argn++;
        if (argn == 1)
        {
            mode = ++cp;
        }
        else if (argn == 2)
        {
            for (cp = mode; *cp; cp++)
                *cp = tolower (*cp);
            for (pf = formats; pf->f_mode; pf++)
            {
                if (!strcmp (pf->f_mode, mode))
                    break;
            }
            if (!pf->f_mode)
            {
                nak (EBADOP);
                exit (0);
            }
            if (!(filename = (*pf->f_rewrite) (origfilename, tp->th_opcode)))
            {
                nak (EACCESS);    /* File denied by mapping rule */
                exit (0);
            }
            if (verbosity >= 1)
            {
                if (filename == origfilename || !strcmp (filename, origfilename))
                    syslog (LOG_NOTICE, "%s from %s filename %s\n",
                            tp->th_opcode == WRQ ? "WRQ" : "RRQ", inet_ntoa (from.sin_addr), filename);
                else
                    syslog (LOG_NOTICE, "%s from %s filename %s remapped to %s\n",
                            tp->th_opcode == WRQ ? "WRQ" : "RRQ", inet_ntoa (from.sin_addr), origfilename, filename);
            }
            ecode = (*pf->f_validate) (filename, tp->th_opcode, pf);
            if (ecode)
            {
                nak (ecode);
                exit (0);
            }
            opt = ++cp;
        }
        else if (argn & 1)
        {
            val = ++cp;
        }
        else
        {
            do_opt (opt, val, &ap);
            opt = ++cp;
        }
    }

    if (!pf)
    {
        nak (EBADOP);
        exit (0);
    }

    if (ap != (ackbuf + 2))
    {
        if (tp->th_opcode == WRQ)
            (*pf->f_recv) (pf, (struct tftphdr *) ackbuf, ap - ackbuf);
        else
            (*pf->f_send) (pf, (struct tftphdr *) ackbuf, ap - ackbuf);
    }
    else
    {
        if (tp->th_opcode == WRQ)
            (*pf->f_recv) (pf, NULL, 0);
        else
            (*pf->f_send) (pf, NULL, 0);
    }
    exit (0);                    /* Request completed */
}
Beispiel #21
0
/*
 * Send the requested file.
 */
void
sendfile(int fd, char *name, char *mode)
{
	register struct tftphdr *ap;       /* data and ack packets */
	struct tftphdr *dp;
	volatile int block = 0, size = 0;
	int n;
	volatile unsigned long amount = 0;
	struct sockaddr_in from;
	socklen_t fromlen;
	volatile int convert;            /* true if doing nl->crlf conversion */
	FILE *file;

	startclock();           /* start stat's clock */
	dp = r_init();          /* reset fillbuf/read-ahead code */
	ap = (struct tftphdr *)ackbuf;
	file = fdopen(fd, "r");
	convert = !strcmp(mode, "netascii");

	signal(SIGALRM, timer);
	do {
		if (block == 0)
			size = makerequest(WRQ, name, dp, mode) - 4;
		else {
		/*      size = read(fd, dp->th_data, SEGSIZE);   */
			size = readit(file, &dp, convert);
			if (size < 0) {
				nak(errno + 100);
				break;
			}
			dp->th_opcode = htons((u_short)DATA);
			dp->th_block = htons((u_short)block);
		}
		timeout = 0;
		(void) sigsetjmp(timeoutbuf, 1);
send_data:
		if (trace)
			tpacket("sent", dp, size + 4);
		n = sendto(f, dp, size + 4, 0,
		    (struct sockaddr *)&s_inn, sizeof(s_inn));
		if (n != size + 4) {
			perror("tftp: sendto");
			goto abort;
		}
		read_ahead(file, convert);
		for ( ; ; ) {
			alarm(rexmtval);
			do {
				fromlen = sizeof (from);
				n = recvfrom(f, ackbuf, sizeof (ackbuf), 0,
				    (struct sockaddr *)&from, &fromlen);
			} while (n <= 0);
			alarm(0);
			if (n < 0) {
				perror("tftp: recvfrom");
				goto abort;
			}
			s_inn.sin_port = from.sin_port;   /* added */
			if (trace)
				tpacket("received", ap, n);
			/* should verify packet came from server */
			ap->th_opcode = ntohs(ap->th_opcode);
			ap->th_block = ntohs(ap->th_block);
			if (ap->th_opcode == ERROR) {
				printf("Error code %d: %s\n", ap->th_code,
					ap->th_msg);
				goto abort;
			}
			if (ap->th_opcode == ACK) {
				volatile int j = 0;

				if (ap->th_block == block) {
					break;
				}
				/* On an error, try to synchronize
				 * both sides.
				 */
				j = synchnet(f);
				if (j && trace) {
					printf("discarded %d packets\n",
							j);
				}
				if (ap->th_block == (block-1)) {
					goto send_data;
				}
			}
		}
		if (block > 0)
			amount += size;
		block++;
	} while (size == SEGSIZE || block == 1);
abort:
	fclose(file);
	stopclock();
	if (amount > 0)
		printstats("Sent", amount);
}
void FstopComms::rx(char ch)
{
    lastrx=micros();

    // store byte
    if(buflen >= PKT_BUFFER)
        buflen=PKT_BUFFER-1;
    cmd[buflen++]=ch;
    incmd=true;

    // got the data we expected...
    if(buflen >= bufwant){
        if(!connected){
            connected=true;
            disp.clear();
            disp.print(CONNECTED);
            lastlcd=lastrx;
        }

        switch(cmd[0]){

            // keepalive; do nothing
        case COM_KEEPALIVE:
            bufwant=1;
            buflen=0;
            incmd=false;
            break;

            // request to read data
        case COM_READ:            
            if(bufwant == 1){
                // wait for the rest of the packet
                bufwant=PKT_HEADER;
            }
            else{
                respondRead();
            }
            break;

            // request to write data
        case COM_WRITE:
            if(bufwant == 1){
                // wait for rest of header
                bufwant=PKT_SHORTHDR;
            }
            else if(bufwant == PKT_SHORTHDR){
                // got length, decide how much packet to wait for
                char len=cmd[PKT_LEN];
                if(len < 1 || len > PKT_MAXREQ){
                    nak(BAD_WRITE);
                }
                else{
                    bufwant=PKT_HEADER+len;  // header+data+checksum
                }
            }
            else{
                // got whole packet
                respondWrite();
            }
            break;

            // disconnect
        default:
            reset();
        }
    }
}
Beispiel #23
0
/*
 * Send the requested file.
 */
void send_file (struct formats *pf)
{
    struct tftphdr *dp, *r_init ();

    register struct tftphdr *ap;    /* ack packet */

    register int size, n;

    volatile int block;

    signal (SIGALRM, timer);
    dp = r_init ();
    ap = (struct tftphdr *) ackbuf;
    block = 1;
    do
    {
        size = readit (file, &dp, pf->f_convert);
        if (size < 0)
        {
            nak (errno + 100);
            goto abort;
        }
        dp->th_opcode = htons ((u_short) DATA);
        dp->th_block = htons ((u_short) block);
        timeout = 0;
        setjmp (timeoutbuf);

      send_data:
        if (send (peer, (const char *) dp, size + 4, 0) != size + 4)
        {
            syslog (LOG_ERR, "tftpd: write: %m\n");
            goto abort;
        }
        read_ahead (file, pf->f_convert);
        for (;;)
        {
            alarm (rexmtval);    /* read the ack */
            n = recv (peer, ackbuf, sizeof (ackbuf), 0);
            alarm (0);
            if (n < 0)
            {
                syslog (LOG_ERR, "tftpd: read: %m\n");
                goto abort;
            }
            ap->th_opcode = ntohs ((u_short) ap->th_opcode);
            ap->th_block = ntohs ((u_short) ap->th_block);

            if (ap->th_opcode == ERROR)
                goto abort;

            if (ap->th_opcode == ACK)
            {
                if ((u_short) ap->th_block == (u_short) block)
                    break;
                /* Re-synchronize with the other side */
                synchnet (peer);
                if ((u_short) ap->th_block == (u_short) (block - 1))
                    goto send_data;
            }

        }
        block++;
    }
    while (size == SEGSIZE);
  abort:
    fclose (file);
}
Beispiel #24
0
/*
 * Send the requested file.
 */
static void sendtftp(struct testcase *test, struct formats *pf)
{
  int size;
  ssize_t n;
  /* These are volatile to live through a siglongjmp */
  volatile unsigned short sendblock; /* block count */
  struct tftphdr * volatile sdp = r_init(); /* data buffer */
  struct tftphdr * const sap = &ackbuf.hdr; /* ack buffer */

  sendblock = 1;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  do {
    size = readit(test, (struct tftphdr **)&sdp, pf->f_convert);
    if(size < 0) {
      nak(errno + 100);
      return;
    }
    sdp->th_opcode = htons((unsigned short)opcode_DATA);
    sdp->th_block = htons(sendblock);
    timeout = 0;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
    if(test->writedelay) {
      logmsg("Pausing %d seconds before %d bytes", test->writedelay,
             size);
      wait_ms(1000*test->writedelay);
    }

    send_data:
    if(swrite(peer, sdp, size + 4) != size + 4) {
      logmsg("write");
      return;
    }
    read_ahead(test, pf->f_convert);
    for(;;) {
#ifdef HAVE_ALARM
      alarm(rexmtval);        /* read the ack */
#endif
      n = sread(peer, &ackbuf.storage[0], sizeof(ackbuf.storage));
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if(got_exit_signal)
        return;
      if(n < 0) {
        logmsg("read: fail");
        return;
      }
      sap->th_opcode = ntohs((unsigned short)sap->th_opcode);
      sap->th_block = ntohs(sap->th_block);

      if(sap->th_opcode == opcode_ERROR) {
        logmsg("got ERROR");
        return;
      }

      if(sap->th_opcode == opcode_ACK) {
        if(sap->th_block == sendblock) {
          break;
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if(sap->th_block == (sendblock-1)) {
          goto send_data;
        }
      }

    }
    sendblock++;
  } while(size == SEGSIZE);
}
Beispiel #25
0
/*
 * Receive a file.
 */
static void recvtftp(struct testcase *test, struct formats *pf)
{
  struct tftphdr *dp;
  struct tftphdr *ap;    /* ack buffer */
  unsigned short block = 0;
  int n, size;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  dp = w_init();
  ap = (struct tftphdr *)ackbuf;
  do {
    timeout = 0;
    ap->th_opcode = htons((u_short)ACK);
    ap->th_block = htons((u_short)block);
    block++;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
send_ack:
    if (send(peer, ackbuf, 4, 0) != 4) {
      logmsg("write: fail\n");
      goto abort;
    }
    write_behind(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);
#endif
      n = recv(peer, dp, PKTSIZE, 0);
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if (n < 0) {                       /* really? */
        logmsg("read: fail\n");
        goto abort;
      }
      dp->th_opcode = ntohs((u_short)dp->th_opcode);
      dp->th_block = ntohs((u_short)dp->th_block);
      if (dp->th_opcode == ERROR)
        goto abort;
      if (dp->th_opcode == DATA) {
        if (dp->th_block == block) {
          break;                         /* normal */
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (dp->th_block == (block-1))
          goto send_ack;                 /* rexmit */
      }
    }

    size = writeit(test, &dp, n - 4, pf->f_convert);
    if (size != (n-4)) {                 /* ahem */
      if (size < 0)
        nak(errno + 100);
      else
        nak(ENOSPACE);
      goto abort;
    }
  } while (size == SEGSIZE);
  write_behind(test, pf->f_convert);

  ap->th_opcode = htons((u_short)ACK);   /* send the "final" ack */
  ap->th_block = htons((u_short)(block));
  (void) send(peer, ackbuf, 4, 0);
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, justquit);           /* just quit on timeout */
  alarm(rexmtval);
#endif
  n = recv(peer, buf, sizeof (buf), 0);  /* normally times out and quits */
#ifdef HAVE_ALARM
  alarm(0);
#endif
  if (n >= 4 &&                          /* if read some data */
      dp->th_opcode == DATA &&           /* and got a data block */
      block == dp->th_block) {           /* then my last ack was lost */
    (void) send(peer, ackbuf, 4, 0);     /* resend final ack */
  }
abort:
  return;
}
Beispiel #26
0
/*
 * Handle initial connection protocol.
 */
static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
{
  char *cp;
  int first = 1, ecode;
  struct formats *pf;
  char *filename, *mode = NULL;
  int error;
  FILE *server;
#ifdef USE_WINSOCK
  DWORD recvtimeout, recvtimeoutbak;
#endif
  char *option = (char *)"mode"; /* mode is implicit */
  int toggle = 1;

  /* Open request dump file. */
  server = fopen(REQUEST_DUMP, "ab");
  if(!server) {
    error = errno;
    logmsg("fopen() failed with error: %d %s", error, strerror(error));
    logmsg("Error opening file: %s", REQUEST_DUMP);
    return -1;
  }

  /* store input protocol */
  fprintf(server, "opcode: %x\n", tp->th_opcode);

  cp = (char *)&tp->th_stuff;
  filename = cp;
  do {
    bool endofit = true;
    while(cp < &buf.storage[size]) {
      if(*cp == '\0') {
        endofit = false;
        break;
      }
      cp++;
    }
    if(endofit)
      /* no more options */
      break;

    /* before increasing pointer, make sure it is still within the legal
       space */
    if((cp+1) < &buf.storage[size]) {
      ++cp;
      if(first) {
        /* store the mode since we need it later */
        mode = cp;
        first = 0;
      }
      if(toggle)
        /* name/value pair: */
        fprintf(server, "%s: %s\n", option, cp);
      else {
        /* store the name pointer */
        option = cp;
      }
      toggle ^= 1;
    }
    else
      /* No more options */
      break;
  } while(1);

  if(*cp) {
    nak(EBADOP);
    fclose(server);
    return 3;
  }

  /* store input protocol */
  fprintf(server, "filename: %s\n", filename);

  for(cp = mode; cp && *cp; cp++)
    if(ISUPPER(*cp))
      *cp = (char)tolower((int)*cp);

  /* store input protocol */
  fclose(server);

  for(pf = formata; pf->f_mode; pf++)
    if(strcmp(pf->f_mode, mode) == 0)
      break;
  if(!pf->f_mode) {
    nak(EBADOP);
    return 2;
  }
  ecode = validate_access(test, filename, tp->th_opcode);
  if(ecode) {
    nak(ecode);
    return 1;
  }

#ifdef USE_WINSOCK
  recvtimeout = sizeof(recvtimeoutbak);
  getsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (char*)&recvtimeoutbak, (int*)&recvtimeout);
  recvtimeout = TIMEOUT*1000;
  setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (const char*)&recvtimeout, sizeof(recvtimeout));
#endif

  if(tp->th_opcode == opcode_WRQ)
    recvtftp(test, pf);
  else
    sendtftp(test, pf);

#ifdef USE_WINSOCK
  recvtimeout = recvtimeoutbak;
  setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO,
             (const char*)&recvtimeout, sizeof(recvtimeout));
#endif

  return 0;
}
Beispiel #27
0
/*
 * Handle initial connection protocol.
 */
static int tftp(struct testcase *test, struct tftphdr *tp, ssize_t size)
{
  char *cp;
  int first = 1, ecode;
  struct formats *pf;
  char *filename, *mode = NULL;
  int error;
  FILE *server;

  /* Open request dump file. */
  server = fopen(REQUEST_DUMP, "ab");
  if(!server) {
    error = ERRNO;
    logmsg("fopen() failed with error: %d %s", error, strerror(error));
    logmsg("Error opening file: %s", REQUEST_DUMP);
    return -1;
  }

  /* store input protocol */
  fprintf(server, "opcode: %x\n", tp->th_opcode);

  cp = (char *)&tp->th_stuff;
  filename = cp;
again:
  while (cp < buf + size) {
    if (*cp == '\0')
      break;
    cp++;
  }
  if (*cp) {
    nak(EBADOP);
    fclose(server);
    return 3;
  }
  if (first) {
    mode = ++cp;
    first = 0;
    goto again;
  }
  /* store input protocol */
  fprintf(server, "filename: %s\n", filename);

  for (cp = mode; cp && *cp; cp++)
    if(ISUPPER(*cp))
      *cp = (char)tolower((int)*cp);

  /* store input protocol */
  fprintf(server, "mode: %s\n", mode);
  fclose(server);

  for (pf = formata; pf->f_mode; pf++)
    if (strcmp(pf->f_mode, mode) == 0)
      break;
  if (!pf->f_mode) {
    nak(EBADOP);
    return 2;
  }
  ecode = validate_access(test, filename, tp->th_opcode);
  if (ecode) {
    nak(ecode);
    return 1;
  }
  if (tp->th_opcode == opcode_WRQ)
    recvtftp(test, pf);
  else
    sendtftp(test, pf);

  return 0;
}
Beispiel #28
0
/*
 * Send the requested file.
 */
void
xmitfile(struct formats *pf)
{
	struct tftphdr *dp;
	struct tftphdr *ap;    /* ack packet */
	int size, n;
	volatile unsigned short block;

	signal(SIGALRM, timer);
	dp = r_init();
	ap = (struct tftphdr *)ackbuf;
	block = 1;
	do {
		size = readit(file, &dp, pf->f_convert);
		if (size < 0) {
			nak(errno + 100);
			goto abort;
		}
		dp->th_opcode = htons((u_short)DATA);
		dp->th_block = htons((u_short)block);
		timeouts = 0;
		(void)setjmp(timeoutbuf);

send_data:
		{
			int i, t = 1;
			for (i = 0; ; i++){
				if (send(peer, dp, size + 4, 0) != size + 4) {
					sleep(t);
					t = (t < 32) ? t<< 1 : t;
					if (i >= 12) {
						syslog(LOG_ERR, "write: %m");
						goto abort;
					}
				}
				break;
			}
		}
		read_ahead(file, pf->f_convert);
		for ( ; ; ) {
			alarm(rexmtval);        /* read the ack */
			n = recv(peer, ackbuf, sizeof (ackbuf), 0);
			alarm(0);
			if (n < 0) {
				syslog(LOG_ERR, "read: %m");
				goto abort;
			}
			ap->th_opcode = ntohs((u_short)ap->th_opcode);
			ap->th_block = ntohs((u_short)ap->th_block);

			if (ap->th_opcode == ERROR)
				goto abort;

			if (ap->th_opcode == ACK) {
				if (ap->th_block == block)
					break;
				/* Re-synchronize with the other side */
				(void) synchnet(peer);
				if (ap->th_block == (block -1))
					goto send_data;
			}

		}
		block++;
	} while (size == SEGSIZE);
abort:
	(void) fclose(file);
}
Beispiel #29
0
/*
 * Receive a file.
 */
static void recvtftp(struct testcase *test, struct formats *pf)
{
  ssize_t n, size;
  recvblock = 0;
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, timer);
#endif
  rdp = w_init();
  rap = (struct tftphdr *)ackbuf;
  do {
    timeout = 0;
    rap->th_opcode = htons((u_short)opcode_ACK);
    rap->th_block = htons((u_short)recvblock);
    recvblock++;
#ifdef HAVE_SIGSETJMP
    (void) sigsetjmp(timeoutbuf, 1);
#endif
send_ack:
    if (swrite(peer, ackbuf, 4) != 4) {
      logmsg("write: fail\n");
      goto abort;
    }
    write_behind(test, pf->f_convert);
    for ( ; ; ) {
#ifdef HAVE_ALARM
      alarm(rexmtval);
#endif
      n = sread(peer, rdp, PKTSIZE);
#ifdef HAVE_ALARM
      alarm(0);
#endif
      if (n < 0) {                       /* really? */
        logmsg("read: fail\n");
        goto abort;
      }
      rdp->th_opcode = ntohs((u_short)rdp->th_opcode);
      rdp->th_block = ntohs((u_short)rdp->th_block);
      if (rdp->th_opcode == opcode_ERROR)
        goto abort;
      if (rdp->th_opcode == opcode_DATA) {
        if (rdp->th_block == recvblock) {
          break;                         /* normal */
        }
        /* Re-synchronize with the other side */
        (void) synchnet(peer);
        if (rdp->th_block == (recvblock-1))
          goto send_ack;                 /* rexmit */
      }
    }

    size = writeit(test, &rdp, (int)(n - 4), pf->f_convert);
    if (size != (n-4)) {                 /* ahem */
      if (size < 0)
        nak(ERRNO + 100);
      else
        nak(ENOSPACE);
      goto abort;
    }
  } while (size == SEGSIZE);
  write_behind(test, pf->f_convert);

  rap->th_opcode = htons((u_short)opcode_ACK);  /* send the "final" ack */
  rap->th_block = htons((u_short)recvblock);
  (void) swrite(peer, ackbuf, 4);
#if defined(HAVE_ALARM) && defined(SIGALRM)
  mysignal(SIGALRM, justtimeout);        /* just abort read on timeout */
  alarm(rexmtval);
#endif
  n = sread(peer, buf, sizeof(buf));     /* normally times out and quits */
#ifdef HAVE_ALARM
  alarm(0);
#endif
  if (n >= 4 &&                          /* if read some data */
      rdp->th_opcode == opcode_DATA &&   /* and got a data block */
      recvblock == rdp->th_block) {      /* then my last ack was lost */
    (void) swrite(peer, ackbuf, 4);      /* resend final ack */
  }
abort:
  return;
}
Beispiel #30
0
/*
 * Handle initial connection protocol.
 */
void tftp (struct tftphdr *tp, int size)
{
    register char *cp;

    int first = 1, ecode;

    register struct formats *pf;

    char *filename, *mode;

    filename = cp = tp->th_stuff;
  again:
    while (cp < buf + size)
    {
        if (*cp == '\0')
            break;
        cp++;
    }
    if (*cp != '\0')
    {
        nak (EBADOP);
        exit (1);
    }
    if (first)
    {
        mode = ++cp;
        first = 0;
        goto again;
    }
    for (cp = mode; *cp; cp++)
        if (isupper (*cp))
            *cp = tolower (*cp);
    for (pf = formats; pf->f_mode; pf++)
        if (strcmp (pf->f_mode, mode) == 0)
            break;
    if (pf->f_mode == 0)
    {
        nak (EBADOP);
        exit (1);
    }
    ecode = (*pf->f_validate) (&filename, tp->th_opcode);
    if (logging)
    {
        syslog (LOG_INFO, "%s: %s request for %s: %s",
                verifyhost (&from), tp->th_opcode == WRQ ? "write" : "read", filename, errtomsg (ecode));
    }
    if (ecode)
    {
        /*
         * Avoid storms of naks to a RRQ broadcast for a relative
         * bootfile pathname from a diskless Sun.
         */
        if (suppress_naks && *filename != '/' && ecode == ENOTFOUND)
            exit (0);
        nak (ecode);
        exit (1);
    }
    if (tp->th_opcode == WRQ)
        (*pf->f_recv) (pf);
    else
        (*pf->f_send) (pf);
    exit (0);
}