Exemple #1
0
int ip232_write(modem_config *cfg, char *data, int len)
{
  int retval;
  int i = 0;
  int double_iac = FALSE;
  char text[1024];
  int text_len = 0;


  log_trace(TRACE_MODEM_OUT, data, len);
  retval = len;
  if (cfg->dce_data.ip232_is_connected) {
    while (i < len) {
      if (double_iac) {
        text[text_len++] = 255;
        double_iac = FALSE;
        i++;
      }
      else {
        if (255 == data[i]) {
          text[text_len++] = 255;
          double_iac = TRUE;
        }
        else {
          text[text_len++] = data[i++];
        }
      }
      if (text_len == sizeof(text)) {
        retval = ip_write(cfg->dce_data.fd, text, text_len);
        text_len = 0;
      }
    }
    if (text_len) {
      retval = ip_write(cfg->dce_data.fd, text, text_len);
    }
  }
  return retval;
}
Exemple #2
0
int send_nvt_command(int fd, nvt_vars *vars, char action, int opt)
{
  char cmd[3];


  cmd[0] = NVT_IAC;
  cmd[1] = action;
  cmd[2] = opt;

  ip_write(fd, cmd, 3);
  vars->term[opt] = action;

  return 0;
}
Exemple #3
0
/* output the IP packet to the ethernet device */
void if_encap(const uint8_t *ip_data, int ip_data_len)
{
    uint8_t buf[1600];
    struct ethhdr *eh = (struct ethhdr *)buf;

    if (ip_data_len + ETH_HLEN > sizeof(buf))
        return;

    if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
        uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
        struct ethhdr *reh = (struct ethhdr *)arp_req;
        struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
        const struct ip *iph = (const struct ip *)ip_data;

        /* If the client addr is not known, there is no point in
           sending the packet to it. Normally the sender should have
           done an ARP request to get its MAC address. Here we do it
           in place of sending the packet and we hope that the sender
           will retry sending its packet. */
        memset(reh->h_dest, 0xff, ETH_ALEN);
        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
        reh->h_source[5] = CTL_ALIAS;
        reh->h_proto = htons(ETH_P_ARP);
        rah->ar_hrd = htons(1);
        rah->ar_pro = htons(ETH_P_IP);
        rah->ar_hln = ETH_ALEN;
        rah->ar_pln = 4;
        rah->ar_op = htons(ARPOP_REQUEST);
        /* source hw addr */
        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
        rah->ar_sha[5] = CTL_ALIAS;
        /* source IP */
        ip_write32h(alias_addr_ip, rah->ar_sip);
        /* target hw addr (none) */
        memset(rah->ar_tha, 0, ETH_ALEN);
        /* target IP */
        ip_write( iph->ip_dst, rah->ar_tip );
        client_ip   = iph->ip_dst;
        slirp_output(arp_req, sizeof(arp_req));
    } else {
        memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
        /* XXX: not correct */
        eh->h_source[5] = CTL_ALIAS;
        eh->h_proto = htons(ETH_P_IP);
        memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
        slirp_output(buf, ip_data_len + ETH_HLEN);
    }
}
Exemple #4
0
int ip232_set_control_lines(modem_config *cfg, int state)
{
  int dcd;
  char cmd[2];


  if (cfg->dce_data.ip232_is_connected) {
    dcd = (state & TIOCM_DTR) ? TRUE : FALSE;
    if (dcd != cfg->dce_data.ip232_dcd) {
      cfg->dce_data.ip232_dcd = dcd;
      cmd[0] = 255;
      cmd[1] = dcd ? 1 : 0;
      ip_write(cfg->dce_data.fd, cmd, sizeof(cmd));
    }
  }
  return 0;
}
Exemple #5
0
void if_encap(const uint8_t *ip_data, int ip_data_len)
{
    uint8_t buf[1600];
    struct ethhdr *eh = (struct ethhdr *)buf;

    if (ip_data_len + ETH_HLEN > sizeof(buf))
        return;

    if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
        uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
        struct ethhdr *reh = (struct ethhdr *)arp_req;
        struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
        const struct ip *iph = (const struct ip *)ip_data;

        memset(reh->h_dest, 0xff, ETH_ALEN);
        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
        reh->h_source[5] = CTL_ALIAS;
        reh->h_proto = htons(ETH_P_ARP);
        rah->ar_hrd = htons(1);
        rah->ar_pro = htons(ETH_P_IP);
        rah->ar_hln = ETH_ALEN;
        rah->ar_pln = 4;
        rah->ar_op = htons(ARPOP_REQUEST);
        
        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
        rah->ar_sha[5] = CTL_ALIAS;
        
        ip_write32h(alias_addr_ip, rah->ar_sip);
        
        memset(rah->ar_tha, 0, ETH_ALEN);
        
        ip_write( iph->ip_dst, rah->ar_tip );
        client_ip   = iph->ip_dst;
        slirp_output(arp_req, sizeof(arp_req));
    } else {
        memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
        
        eh->h_source[5] = CTL_ALIAS;
        eh->h_proto = htons(ETH_P_IP);
        memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
        slirp_output(buf, ip_data_len + ETH_HLEN);
    }
}
Exemple #6
0
int main(int argc, char *argv[]) {
  modem_config cfg[64];
  int modem_count;
  int port=0;

  char *ip_addr = NULL; /* gwb */

  unsigned char all_busy[255];

  pthread_t thread_id;
  int i;
  int rc;

  int sSocket = 0;
  fd_set readfs; 
  int max_fd=0;
  int accept_pending=FALSE;

  int res=0;
  unsigned char buf[255];

  int cSocket;

  log_init();

  LOG_ENTER();

  log_set_level(LOG_FATAL);

  mdm_init();

  pb_init();
  
  signal(SIGIO,SIG_IGN); /* Some Linux variant term on SIGIO by default */

  modem_count = init(argc, argv, cfg, 64, &ip_addr, &port,all_busy,sizeof(all_busy)); /* gwb */

  sSocket = ip_init_server_conn(ip_addr, port);


  for(i=0;i<modem_count;i++) {
    if( -1 == pipe(cfg[i].data.mp[0])) {
      ELOG(LOG_FATAL,"Bridge task incoming IPC pipe could not be created");
      exit(-1);
    }
    if( -1 == pipe(cfg[i].data.mp[1])) {
      ELOG(LOG_FATAL,"Bridge task outgoing IPC pipe could not be created");
      exit(-1);
    }
    if(dce_init_conn(&cfg[i]) < 0) {
      LOG(LOG_FATAL,"Could not open serial port %s",cfg->dce_data.tty);
      exit(-1);
    }
    cfg[i].line_data.sfd=sSocket;

    rc=pthread_create(&thread_id,NULL,*run_bridge,(void *)&cfg[i]);
    if(rc < 0) {
        ELOG(LOG_FATAL,"IP thread could not be started");
        exit(-1);
    }

  }
  for(;;) {
    FD_ZERO(&readfs);
    max_fd=0;
    for(i=0;i<modem_count;i++) {
      FD_SET(cfg[i].data.mp[0][0], &readfs); 
      max_fd=MAX(max_fd,cfg[i].data.mp[0][0]);
    }
    if(accept_pending==FALSE) {
      max_fd=MAX(max_fd,sSocket);
      FD_SET(sSocket, &readfs); 
    }
    LOG(LOG_ALL,"Waiting for incoming connections and/or indicators");
    select(max_fd+1, &readfs, NULL, NULL, NULL);
    for(i=0;i<modem_count;i++) {
      if (FD_ISSET(cfg[i].data.mp[0][0],&readfs)) {  // child pipe
        res = read(cfg[i].data.mp[0][0],buf,sizeof(buf) -1);
        if(res > -1) {
          buf[res]=0;
          LOG(LOG_DEBUG,"modem core #%d sent response '%c'",i,buf[0]);
          accept_pending=FALSE;
        }
      }
    }
    if (FD_ISSET(sSocket,&readfs)) {  // IP traffic
      if(!accept_pending) {
        LOG(LOG_DEBUG,"Incoming connection pending");
        // first try for a modem that is listening.
        for(i=0;i<modem_count;i++) {
          if(cfg[i].s[0] != 0 && cfg[i].off_hook == FALSE) {
            // send signal to pipe saying pick up...
            LOG(LOG_DEBUG,"Sending incoming connection to listening modem #%d",i);
            writePipe(cfg[i].data.mp[1][1],MSG_ACCEPT);  
            accept_pending=TRUE;
            break;
          }
        }
        // now, send to any non-active modem.
        for(i=0;i<modem_count;i++) {
          if(cfg[i].off_hook== FALSE) {
            // send signal to pipe saying pick up...
            LOG(LOG_DEBUG,"Sending incoming connection to non-connected modem #%d",i);
            writePipe(cfg[i].data.mp[1][1],MSG_ACCEPT);  
            accept_pending=TRUE;
            break;
          }
        }
        if(i==modem_count) {
          LOG(LOG_DEBUG,"No open modem to send to, send notice and close");
          // no connections.., accept and print error
          cSocket=ip_accept(sSocket);
          if(cSocket > -1) {
            if(strlen(all_busy) < 1) {
              ip_write(cSocket,(unsigned char*)MDM_BUSY,strlen(MDM_BUSY));
            } else {
              writeFile(all_busy,cSocket);
            }
            close(cSocket);
          }
        }
      }
    }
  }
  LOG_EXIT();
  return rc;
}
Exemple #7
0
int
rawip_usrreq(struct socket * so, 
   struct mbuf *  m,
   struct mbuf *  nam)
{
   int   e;    /* error from IP stack */
   PACKET pkt; /* packet for sending */
   struct sockaddr_in * sin;
   struct ipraw_ep * ep;
   ip_addr fhost; /* host to send to/recv from (network byte order) */
   ip_addr lhost; /* local IP address to bind to (network byte order) */
   u_char prot;
   struct ip * pip;
   int   req;
   NET   ifp;     /* ptr to network interface structure */

   req = so->so_req;    /* get request from socket struct */

   switch (req) 
   {
   case PRU_ATTACH:
      /* fake small windows so sockets asks us to move data */
      so->so_rcv.sb_hiwat = so->so_snd.sb_hiwat = 
         ip_raw_maxalloc(so->so_options & SO_HDRINCL);
      /* make a raw IP endpoint */
      prot = (u_char)(MBUF2LONG(nam));
      /* unlock the net resource; IP will immediatly re-lock it */
      UNLOCK_NET_RESOURCE(NET_RESID);
      ep = ip_raw_open(prot, 0L, 0L, rawip_soinput, so);
      LOCK_NET_RESOURCE(NET_RESID);
      if (!ep)
         return(EINVAL);
      return 0;
   case PRU_DETACH:
      /* delete the raw IP endpoint */
      ep = rawip_lookup(so);
      if (!ep)
         return(EINVAL);
      /* unlock the net resource; IP will immediatly re-lock it */
      UNLOCK_NET_RESOURCE(NET_RESID);
      ip_raw_close(ep);
      LOCK_NET_RESOURCE(NET_RESID);
      return 0;
   case PRU_CONNECT:
      /* "connect" the raw IP endpoint to a peer IP address:
       * this sets a filter for received IP datagrams and sets
       * a default address for sending
       */
      /* fall through to shared bind logic */
   case PRU_BIND:
      /* do bind parameters lookups and tests */
      if (nam == NULL)
         return(EINVAL);
      sin = mtod(nam, struct sockaddr_in *);
      if (sin == NULL)
         return(EINVAL);
      if (nam->m_len != sizeof (*sin))
         return(EINVAL);
      ep = rawip_lookup(so);
      if (!ep)
         return(EINVAL);
      if (req == PRU_BIND)
      {
         /* bind the socket to a local interface IP address.
          *
          * if the caller-supplied address is INADDR_ANY,
          * don't bind to a specific address; else, 
          * make sure the caller-supplied address is
          * an interface IP address and if so, bind to that
          */
         if (sin->sin_addr.s_addr == INADDR_ANY)
         {
            lhost = 0L;
         }
         else
         {
            lhost = sin->sin_addr.s_addr;
            /* verify that lhost is a local interface address */
            for (ifp = (NET)(netlist.q_head); ifp; ifp = ifp->n_next)
               if (ifp->n_ipaddr == lhost)
                  break;
            if (ifp == NULL)
               return(EADDRNOTAVAIL);
         }

         /* bind the endpoint */
         ep->ipr_laddr = lhost;
      }
      else /* PRU_CONNECT */
      {
         /* connect the socket to a remote IP address.
          *
          * if the caller-supplied address is INADDR_ANY,
          * use the wildcard address; else, use the caller-
          * supplied address
          */
         if (sin->sin_addr.s_addr == INADDR_ANY)
            fhost = 0L;
         else
            fhost = sin->sin_addr.s_addr;
         /* connect the IP endpoint */
         ep->ipr_faddr = fhost;
         /* mark the socket as connected or disconnected, as appropriate */
         if (fhost != 0L) {
            so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING);
            so->so_state |= SS_ISCONNECTED;
         }
         else
         {
            so->so_state &= ~SS_ISCONNECTED;
         }
         /* since socket was in listen state, packets may be queued */
         sbflush(&so->so_rcv);   /* dump these now */
      }
      return 0;
   case PRU_SEND:
      /* do parameter lookups and tests */
      if (!m)  /* no data passed? */
         return(EINVAL);

      ep = rawip_lookup(so);
      if (!ep)
      {
         m_free(m);
         /* may be bogus socket, but more likely the connection may 
         have closed due to ICMP dest unreachable from other side. */
         return(ECONNREFUSED);
      }

      if (nam == NULL)  /* no sendto() info passed, must be send() */
      {
         if (!(so->so_state & SS_ISCONNECTED))
            return (ENOTCONN);
         fhost = ep->ipr_faddr;
      }
      else 
      {
         if (so->so_state & SS_ISCONNECTED)
            return (EISCONN);
         if (nam->m_len != sizeof (*sin))
         {
            dtrap();
            return (EINVAL);
         }
         sin = mtod(nam, struct sockaddr_in *);
         fhost = sin->sin_addr.s_addr;
      }

      /* since our pkt->nb_buff size is tied to max packet size, we 
       * assume our raw IP datagrams are always in one mbuf and that the 
       * mbuf -- but check anyway
       */
      if (m->m_len > (unsigned)ip_raw_maxalloc(so->so_options & SO_HDRINCL))
      {
         dtrap(); /* should never happen */
         return EMSGSIZE;  /* try to recover */
      }
      /* get a packet buffer for send */
      pkt = ip_raw_alloc(m->m_len, so->so_options & SO_HDRINCL);
      if (!pkt)
      {
         m_free(m);
         return ENOBUFS;   /* report buffer shortages */
      }
      MEMCPY(pkt->nb_prot, m->m_data, m->m_len);
      pkt->nb_plen = m->m_len;
      /* finished with mbuf, free it now */
      m_free(m);
      pkt->fhost = fhost;

      /* if we're being asked to send to 255.255.255.255 (a local-net
       * broadcast), figure out which interface to send the broadcast
       * on, based on the IP address that the socket is bound to: if
       * it has been bound to an interface address, we should send the
       * broadcast on that interface; else, we look for the first
       * interface that can support broadcasts and is up; if we still
       * don't have an interface we look for the first interface that
       * is up; if (after all that) we don't have an interface then we
       * fail with error EADDRNOTAVAIL; and finally, if we're built
       * for a single-homed configuration where there's only one
       * interface, we might as well use it, so we do.  
       */
      if (fhost == 0xffffffff)
      {
#ifdef MULTI_HOMED
         if (ep->ipr_laddr != 0L)
         {
            for (ifp = (NET)(netlist.q_head); ifp; ifp = ifp->n_next)
               if (ifp->n_ipaddr == ep->ipr_laddr)
                  break;
         }
         else {
            for (ifp = (NET)(netlist.q_head); ifp; ifp = ifp->n_next)
               if ((ifp->n_flags & NF_BCAST) &&
                   (ifp->n_mib) && (ifp->n_mib->ifAdminStatus == NI_UP))
                  break;
         }
         if (ifp == NULL)
         {
            for (ifp = (NET)(netlist.q_head); ifp; ifp = ifp->n_next)
               if ((ifp->n_mib) && (ifp->n_mib->ifAdminStatus == NI_UP))
                  break;
            if (ifp == NULL)
               return(EADDRNOTAVAIL);
         }
         pkt->net = ifp;
#else  /* single-homed */
         pkt->net = (NET)(netlist.q_head);
#endif /* MULTI_HOMED */
      }

#ifdef IP_MULTICAST

      /* If the socket has an IP moptions structure for multicast options,
       * place a pointer to this structure in the PACKET structure.
       */
      if (so->inp_moptions)
         pkt->imo = so->inp_moptions;

#endif   /* IP_MULTICAST */

      if (so->so_options & SO_HDRINCL)
      {
         UNLOCK_NET_RESOURCE(NET_RESID);
         e = ip_raw_write(pkt);
         LOCK_NET_RESOURCE(NET_RESID);
      }
      else
      {
         pip = (struct ip *)(pkt->nb_prot - IPHSIZ);
         if (ep->ipr_laddr)
            pip->ip_src = ep->ipr_laddr;
         else
         {
            if (fhost == 0xffffffff)
               pip->ip_src = pkt->net->n_ipaddr;
            else
               pip->ip_src = ip_mymach(fhost);
         }
         pip->ip_dest = fhost;
         UNLOCK_NET_RESOURCE(NET_RESID);
         e = ip_write(ep->ipr_prot, pkt);
         LOCK_NET_RESOURCE(NET_RESID);
      }         
      if (e < 0) 
         return(e);
      return 0;
   case PRU_SOCKADDR:
      /* fall through to share PRU_PEERADDR prefix */
   case PRU_PEERADDR:
      if (nam == NULL)
         return(EINVAL);
      sin = mtod(nam, struct sockaddr_in *);
      if (sin == NULL)
         return(EINVAL);
      ep = rawip_lookup(so);
      if (!ep)
         return(EINVAL);
      sin->sin_port = 0;
      nam->m_len = sizeof(*sin);
      if (req == PRU_SOCKADDR)
      {
         sin->sin_addr.s_addr = ep->ipr_laddr;
      }
      else /* PRU_PEERADDR */
      {
         sin->sin_addr.s_addr = ep->ipr_faddr;
      }
      return 0;
   case PRU_DISCONNECT:
   case PRU_RCVD:
      dtrap();
      return 0;
   case PRU_LISTEN:     /* don't support these for raw IP */
   case PRU_ACCEPT:
   default:
      return EOPNOTSUPP;
   }
}
Exemple #8
0
int
icmpEcho(ip_addr host,  /* host to ping - 32 bit, network-endian */
   char *   data,       /* ping data, NULL if don't care */
   unsigned datalen,     /* length of data to attach to ping request */
   unshort  pingseq)    /* ping sequence number */
{
   PACKET   p;
   int      ip_err;
   struct ping *  e;
   struct ip *    pip;

   LOCK_NET_RESOURCE(FREEQ_RESID);
   p = pk_alloc(PINGHDRSLEN + datalen);
   UNLOCK_NET_RESOURCE(FREEQ_RESID);
   if (!p)
   {
#ifdef   NPDEBUG
      if (NDEBUG & IPTRACE)
         dprintf("icmp: can't alloc packet\n");
#endif
      return(ENP_NOBUFFER);
   }

   p->nb_prot = p->nb_buff + PINGHDRSLEN;
   p->nb_plen = datalen;
   p->fhost = host;

   if(host == 0xFFFFFFFF)  /* broadcast? */
      p->net = nets[0];    /* then use first iface */

   /* copy in data field */
   if (data)
   {
      MEMCPY(p->nb_prot, data, datalen);
   }
   else  /* caller didn't specify data */
   {
      unsigned   donedata;
      strcpy(p->nb_prot, pingdata);
      donedata = (unsigned)strlen(pingdata);
      while (donedata < datalen)
      {
         *(p->nb_prot + donedata) = (char)((donedata) & 0x00FF);
         donedata++;
      }
   }

   /* adjust packet pointers to icmp ping header */
   p->nb_prot -= sizeof(struct ping);
   p->nb_plen += sizeof(struct ping);

   /* fill in icmp ping header */
   e = (struct ping *)p->nb_prot;
   e->ptype = ECHOREQ;
   e->pcode = 0;
   e->pid = 0;
   e->pseq = pingseq;

   /* Calculate the checksum */
   e->pchksum = 0;
   if (datalen & 1)  /* if data size is odd, pad with a zero */
      *((char*)(e+1) + datalen) = 0;

   e->pchksum = ~cksum(e, (ICMPSIZE+datalen+1)>>1);

   /* need to fill in IP addresses at this layer too */
   pip = (struct ip *)(p->nb_prot - sizeof(struct ip));
   pip->ip_src = ip_mymach(host);
   pip->ip_dest = host;

   LOCK_NET_RESOURCE(NET_RESID);
   ip_err = ip_write(ICMP_PROT, p);    /* send down to IP layer */
   UNLOCK_NET_RESOURCE(NET_RESID);

   /* Errors are negative. A zero means send was OK. a positive number
    * usually means we had to ARP. Assume this will work and count a send.
    */
   if(ip_err < 0)
   {
#ifdef   NPDEBUG
      if (NDEBUG & NETERR)
         dprintf("icmp: can't send echo request\n");
#endif
      /* rfc 1156 seems to say not to count these. (pg 48) -JB- */
      /* LOCK_NET_RESOURCE(FREEQ_RESID); */
      /* pk_free(p); */
      /* UNLOCK_NET_RESOURCE(FREEQ_RESID); */
      return(ip_err);
   }
   /* fall to here if we sent echo request OK */
   icmp_mib.icmpOutMsgs++;
   icmp_mib.icmpOutEchos++;

   return(0);
}
Exemple #9
0
int parse_nvt_subcommand(int fd, nvt_vars *vars, unsigned char *data, int len, int speed)
{
  // overflow issue, again...
  nvtOption opt = data[2];
  char resp[100];
  char *response = resp + 3;
  int resp_len = 0;
  int response_len = 0;
  char tty_type[] = "VT100";
  int rc;
  int slen = 0;
  char buf[50];


  for (rc = 2; rc < len - 1; rc++) {
    if (NVT_IAC == data[rc])
      if (NVT_SE == data[rc + 1]) {
        rc += 2;
        break;
      }
  }

  if (rc > 5 && (NVT_SB_SEND == data[3])) {
    switch (opt) {
    case NVT_OPT_TERMINAL_TYPE:
    case NVT_OPT_TERMINAL_SPEED:
    case NVT_OPT_X_DISPLAY_LOCATION:   // should not have to have these
    case NVT_OPT_ENVIRON:	       // but telnet seems to expect.
    case NVT_OPT_NEW_ENVIRON:	       // them.
      response[response_len++] = NVT_SB_IS;
      switch (opt) {
      case NVT_OPT_TERMINAL_TYPE:
        slen = strlen(tty_type);
        strncpy(response + response_len, tty_type, slen);
        response_len += slen;
        break;

      case NVT_OPT_TERMINAL_SPEED:
	sprintf(buf, "%i,%i", speed, speed);
	slen = strlen(buf);
	strncpy(response + response_len, buf, slen);
	response_len += slen;
	break;
	
      default:
	break;
      }
      break;

    default:
      break;
    }
  }

  if (response_len) {
    resp[resp_len++] = NVT_IAC;
    resp[resp_len++] = NVT_SB;
    resp[resp_len++] = opt;
    resp_len += response_len;
    resp[resp_len++] = NVT_IAC;
    resp[resp_len++] = NVT_SE;
    ip_write(fd, resp, resp_len);
  }
  return rc;
}
Exemple #10
0
int parse_nvt_command(int fd, nvt_vars *vars, nvtCommand action, nvtOption opt, int parity)
{
  char resp[3];
  int accept = FALSE;
  

  resp[0] = NVT_IAC;
  resp[2] = opt;

  switch (opt) {
  case NVT_OPT_TRANSMIT_BINARY:
    switch (action) {
    case NVT_DO:
      if (!parity) {
	LOG(LOG_INFO, "Enabling telnet binary xmit");
	vars->binary_xmit = TRUE;
	accept = TRUE;
      }
      break;
    case NVT_DONT:
      LOG(LOG_INFO, "Disabling telnet binary xmit");
      vars->binary_xmit = FALSE;
      accept = TRUE;
      break;
    case NVT_WILL:
      if (!parity) {
	LOG(LOG_INFO, "Enabling telnet binary recv");
	vars->binary_recv = TRUE;
	accept = TRUE;
      }
      break;
    case NVT_WONT:
      LOG(LOG_INFO, "Disabling telnet binary recv");
      vars->binary_recv = FALSE;
      accept = TRUE;
      break;

    default:
      break;
    }
    resp[1] = get_nvt_cmd_response(action, accept);
    break;

  case NVT_OPT_NAWS:
  case NVT_OPT_TERMINAL_TYPE:
  case NVT_OPT_TERMINAL_SPEED:
  case NVT_OPT_SUPPRESS_GO_AHEAD:
  case NVT_OPT_ECHO:
  case NVT_OPT_X_DISPLAY_LOCATION:     // should not have to have these
  case NVT_OPT_ENVIRON:		       // but telnet seems to expect.
  case NVT_OPT_NEW_ENVIRON:	       // them.
    resp[1] = get_nvt_cmd_response(action, TRUE);
    break;

  default:
    resp[1] = get_nvt_cmd_response(action, FALSE);
    break;
  }
  ip_write(fd, resp, 3);
  return 0;
}
Exemple #11
0
int
ip_output(struct mbuf * data, struct   ip_socopts * so_optsPack) /* mbuf chain with data to send */
{
   struct ip * bip;
   struct tcphdr *   tcpp;
   PACKET pkt;
   struct mbuf *  m1, * m2, * mtmp; /* temp mbuf pointers */
   int   e;    /* error holder */
   int   total;

   /* reassemble mbufs into a contiguous packet. Do this with as 
    * little copying as possible. Typically the mbufs will be either 
    * 1) a single mbuf with iptcp header info only (e.g.tcp ACK 
    * packet), or 2) iptcp header with data mbuf chained to it, or 3) 
    * #2) with a tiny option data mbuf between header and data. 
    */
   if ((data->m_next))
   {
      m1 = data;
      m2 = data->m_next;

      /* If m2 is small (e.g. options), copy it to m1 and free it */
      while (m2 && (m2->m_len < 10))
      {
         pkt = m1->pkt;
         if ((pkt->nb_buff + pkt->nb_blen) > /* make sure m2 will fit in m1 */
             (m1->m_data + m1->m_len + m2->m_len))
         {
            MEMCPY((m1->m_data + m1->m_len), m2->m_data, m2->m_len);
            m1->m_len += m2->m_len;
            m1->m_next = m2->m_next;
            m_free(m2);    /* free this m2.... */
            m2 = m1->m_next;  /* ...and thread the next one */
            tcpstat.tcps_oappends++;
         }
         else     /* if won't fit, fall to next copy */
            break;
      }

      while (m2)  /* If we still have two or more buffers, more copying: */
      {
         /* try prepending m1 to m2, first see if it fits: */
         e = m2->m_data - m2->pkt->nb_buff;  /* e is prepend space */
         if (e < MaxLnh)
         { 
#ifdef NPDEBUG
            dprintf("nptcp: MaxLnh:%d, e:%d\n", MaxLnh, e);
#endif
            panic("tcp_out:mbuf-nbuf");   /* sanity check */
         }

         if ((m1->m_len < (unsigned)(e - MaxLnh))  /* leave room for MAC */
             && ((m1->m_len & (ALIGN_TYPE - 1)) == 0)  /* and stay aligned */
             && ((m2->m_data - m2->pkt->nb_buff) == HDRSLEN))   /* be at start */
         {
            MEMCPY((m2->m_data - m1->m_len), m1->m_data, m1->m_len);
            m2->m_data -= m1->m_len;   /* fix target to reflect prepend */
            m2->m_len += m1->m_len;
            m_free(m1);    /* free head (copied) mbuf */
            data = m1 = m2;   /* move other mbufs up the chain */
            m2 = m2->m_next;  /* loop to while(m2) test */
            tcpstat.tcps_oprepends++;
         }
         else     /* if won't fit, fall to next copy */
            break;
      }

      if (m2)  /* If all else fails, brute force copy: */
      {
         total = 0;
         for (mtmp = m1; mtmp; mtmp = mtmp->m_next)
            total += mtmp->m_len;
         LOCK_NET_RESOURCE(FREEQ_RESID);
         pkt = pk_alloc(total + HDRSLEN);
         UNLOCK_NET_RESOURCE(FREEQ_RESID);
         if (!pkt)
            return ENOBUFS;
         pkt->nb_prot = pkt->nb_buff + MaxLnh;

         mtmp = m1;
         while (mtmp)
         {
            MEMCPY(pkt->nb_prot, mtmp->m_data, mtmp->m_len);
            pkt->nb_prot += mtmp->m_len;
            pkt->nb_plen += mtmp->m_len;
            m2 = mtmp;
            mtmp = mtmp->m_next;
            if (m2 != data)   /* save original head */
               m_free(m2);
            tcpstat.tcps_ocopies++;
         }
         pkt->nb_prot -= total;     /* fix data pointer */

         /* release the original mbufs packet install the new one */
         LOCK_NET_RESOURCE(FREEQ_RESID);
         pk_free(data->pkt);
         UNLOCK_NET_RESOURCE(FREEQ_RESID);
         data->pkt = pkt;
         data->m_len = pkt->nb_plen;
         data->m_next = NULL;
         data->m_data = pkt->nb_prot;
         data->m_len = total;
      }
   }

   if ((data->m_data < (data->pkt->nb_buff + MaxLnh)))
      panic("ip_output: overflow");

   pkt = data->pkt;

   /* do we have options? */
   if (so_optsPack)
	   pkt->soxopts = so_optsPack;   /* yup */
#ifdef IP6_ROUTING
   else
   {
      panic("ip_output: no so_optsPack for the IPv6 scope");     
   }
#endif

   /* fill in dest host for IP layer */
   bip = (struct ip *)data->m_data;
   pkt->fhost = bip->ip_dest;

   /* make enough IP header for cksum calculation */
   bip->ip_ver_ihl = 0x45;
   bip->ip_len = htons(bip->ip_len);   /* make net endian for calculation */
   tcpp = (struct tcphdr *)ip_data(bip);
#ifdef CSUM_DEMO
   if (!(tcpp->th_flags & TH_SYN))
   tcpp->th_flags |= TH_PUSH;     /* force the PSH flag in TCP hdr */
#endif
   tcpp->th_sum = tcp_cksum(bip);

   pkt->nb_prot = (char*)(bip + 1);    /* point past IP header */
   pkt->nb_plen = data->m_len - sizeof(struct ip);

   e = ip_write(IPPROTO_TCP, pkt);

   /* ip_write() is now responsable for data->pkt, so... */
   data->pkt = NULL;
   m_freem(data);

   if (e < 0)
   {
      /* don't report dropped sends, it causes socket applications to 
      bail when a TCP retry will fix the problem */
      if (e == SEND_DROPPED)
         return 0;
      return e;
   }
   else
      return 0;
}