示例#1
0
文件: slip.c 项目: dieterdeyke/WAMPES
/* Process SLIP line input */
void
slip_rx(
struct iface *iface)
{
	int c;
	struct mbuf *bp;
	register struct slip *sp;
	int cdev;
	uint8 *cp;
	uint8 buf[4096];
	int cnt;
	int xdev;

	xdev = iface->xdev;
	sp = &Slip[xdev];
	cdev = sp->iface->dev;

	cnt = (*sp->get)(cdev,cp=buf,sizeof(buf));
	while(--cnt >= 0){
		if((bp = slip_decode(sp,*cp++)) == NULL)
			continue;       /* More to come */

		if (sp->iface->trace & IF_TRACE_RAW)
			raw_dump(sp->iface,IF_TRACE_IN,bp);

	if(sp->slcomp){
		if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
			if ( slhc_uncompress(sp->slcomp, &bp) <= 0 ) {
				free_p(&bp);
				sp->errors++;
				continue;
			}
		} else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
			bp->data[0] &= 0x4f;
			if ( slhc_remember(sp->slcomp, &bp) <= 0 ) {
				free_p(&bp);
				sp->errors++;
				continue;
			}
		}
	}
		net_route( sp->iface, &bp);
		/* Especially on slow machines, serial I/O can be quite
		 * compute intensive, so release the machine before we
		 * do the next packet.  This will allow this packet to
		 * go on toward its ultimate destination. [Karn]
		 */
		kwait(NULL);
	}
}
示例#2
0
文件: ipip.c 项目: dieterdeyke/WAMPES
static int ipip_send(struct mbuf **bpp, struct iface *ifp, int32 gateway, uint8 tos)
{

  char buf[MAX_FRAME];
  int l;
  struct edv_t *edv;
  struct sockaddr_in addr;

  dump(ifp, IF_TRACE_OUT, *bpp);
  ifp->rawsndcnt++;
  ifp->lastsent = secclock();

  if (ifp->trace & IF_TRACE_RAW)
    raw_dump(ifp, -1, *bpp);

  l = pullup(bpp, buf, sizeof(buf));
  if (l <= 0 || *bpp) {
    free_p(bpp);
    return -1;
  }

  edv = (struct edv_t *) ifp->edv;

  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(gateway);
  addr.sin_port = htons(edv->port);

  sendto(edv->fd, buf, l, 0, (struct sockaddr *) &addr, sizeof(addr));

  return l;
}
示例#3
0
 void set_stack_frame_size(cell frame_size) {
   FACTOR_ASSERT(size() < 0xFFFFFF);
   FACTOR_ASSERT(!free_p());
   FACTOR_ASSERT(frame_size % 16 == 0);
   FACTOR_ASSERT(frame_size <= 0xFF0);
   header = (header & 0xFFFFFF) | (frame_size << 20);
 }
示例#4
0
文件: ip.c 项目: zidier215/tcpip
/* Delete a fragment, return next one on queue */
static void
freefrag(
struct frag *fp
){
	free_p(&fp->buf);
	free(fp);
}
示例#5
0
文件: ip.c 项目: zidier215/tcpip
/* Free all resources associated with a reassembly descriptor */
static void
free_reasm(
struct reasm *r
){
	register struct reasm *rp;
	struct reasm *rplast = NULL;
	register struct frag *fp;

	for(rp = Reasmq;rp != NULL;rplast = rp,rp=rp->next)
		if(r == rp)
			break;
	if(rp == NULL)
		return;	/* Not on list */

	stop_timer(&rp->timer);
	/* Remove from list of reassembly descriptors */
	if(rplast != NULL)
		rplast->next = rp->next;
	else
		Reasmq = rp->next;

	/* Free any fragments on list, starting at beginning */
	while((fp = rp->fraglist) != NULL){
		rp->fraglist = fp->next;
		free_p(&fp->buf);
		free(fp);
	}
	free(rp);
}
示例#6
0
static int ethertap_send(struct mbuf **bpp, struct iface *ifp, int32 gateway, uint8 tos)
{

  int l;
  struct edv_t *edv;
  struct ethertap_packet ethertap_packet;

  static const unsigned char ethernet_header[16] = {
    0x00, 0x00,                                 /* ??? */
    0xfe, 0xfd, 0x00, 0x00, 0x00, 0x00,         /* Destination address (kernel ethertap module) */
    0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,         /* Source address (WAMPES ethertap module) */
    0x08, 0x00                                  /* Protocol (IP) */
  };

  edv = (struct edv_t *) ifp->edv;
  dump(ifp, IF_TRACE_OUT, *bpp);
  ifp->rawsndcnt++;
  ifp->lastsent = secclock();
  if (ifp->trace & IF_TRACE_RAW) {
    raw_dump(ifp, -1, *bpp);
  }
  l = pullup(bpp, ethertap_packet.data, sizeof(ethertap_packet.data));
  if (l <= 0 || *bpp) {
    free_p(bpp);
    return -1;
  }
  memcpy(ethertap_packet.ethernet_header, (const char *) ethernet_header, sizeof(ethernet_header));
  write(edv->fd, &ethertap_packet, l + sizeof(ethertap_packet.ethernet_header));
  return l;
}
示例#7
0
文件: ip.c 项目: zidier215/tcpip
/* Decrement the IP TTL field in each packet on the send queue. If
 * a TTL goes to zero, discard the packet.
 */
void
ttldec(
struct iface *ifp
){
	struct mbuf *bp,*bpprev,*bpnext;
	struct qhdr qhdr;
	struct ip ip;

	bpprev = NULL;
	for(bp = ifp->outq; bp != NULL;bpprev = bp,bp = bpnext){
		bpnext = bp->anext;
		pullup(&bp,&qhdr,sizeof(qhdr));
		ntohip(&ip,&bp);
		if(--ip.ttl == 0){
			/* Drop packet */
			icmp_output(&ip,bp,ICMP_TIME_EXCEED,0,NULL);
			if(bpprev == NULL)	/* First on queue */
				ifp->outq = bpnext;
			else
				bpprev->anext = bpnext;
			free_p(&bp);
			bp = bpprev; 
			continue;
		}
		/* Put IP and queue headers back, restore to queue */
		htonip(&ip,&bp,0);
		pushdown(&bp,&qhdr,sizeof(qhdr));
		if(bpprev == NULL)	/* First on queue */
			ifp->outq = bp;
		else
			bpprev->anext = bp;
		bp->anext = bpnext;
	}
}
示例#8
0
文件: tcpsock.c 项目: zidier215/tcpip
int
so_tcp_send(struct usock *up,struct mbuf **bpp,struct sockaddr *to)
{
	struct tcb *tcb;
	long cnt;

	if((tcb = up->cb.tcb) == NULL){
		free_p(bpp);
		errno = ENOTCONN;
		return -1;
	}		
	cnt = send_tcp(tcb,bpp);

	while((tcb = up->cb.tcb) != NULL &&
	 tcb->sndcnt > tcb->window){
		/* Send queue is full */
		if(up->noblock){
			errno = EWOULDBLOCK;
			return -1;
		} else if((errno = kwait(up)) != 0){
			return -1;
		}
	}
	if(tcb == NULL){
		errno = ENOTCONN;
		return -1;
	}
	return cnt;
}
示例#9
0
/* TCP discard server */
static void
disc_server(
    struct tcb *tcb,
    int32 cnt)
{
    struct mbuf *bp;

    if (recv_tcp(tcb, &bp, 0) > 0)
        free_p(&bp);
}
示例#10
0
文件: mbuf.c 项目: hailynch/jnos2
void
refiq()
{
    register struct mbuf *bp;
    char i_state;
#ifdef  PI              /* Temp hack to satisfy PI DMA requirements */
    int32 dma_abs;  /* TEMP */
    int16 dma_page; /* TEMP */
#endif
  
    /* Empty the garbage */
    if(Garbq != NULLBUF){
        i_state = dirps();
        bp = Garbq;
        Garbq = NULLBUF;
        restore(i_state);
        free_p(bp);
    }
    /* Replenish interrupt buffer pool */ /* G1EMM and HB9RWM fix */
    while((Intqlen < Nibufs) && (Memthresh < availmem()) ){
#ifdef notdef
        while(Intqlen < Nibufs){
#endif
            if((bp = alloc_mbuf(Ibufsize)) == NULLBUF)
                break;
#ifdef  PI              /* Temp hack to satisfy PI DMA requirements */
            dma_abs = ((long)FP_SEG(bp->data) << 4) + (long)FP_OFF(bp->data);
            dma_page = dma_abs >> 16;
            if(((dma_abs+Ibufsize) >> 16) != dma_page){
                i_state = dirps();
                bp->next = Garbq;
                Garbq = bp;
                restore(i_state);
                continue;
            }
#endif
  
            i_state = dirps();
            bp->next = Intq;
            Intq = bp;
            Intqlen++;
            restore(i_state);
        }
        if(Iminfree == -1)
            Iminfree = Intqlen;
    }
  
    void
    iqstat()
    {
        tprintf("Intqlen %u Ibufsize %u Iminfree %u Ibuffail %lu Imaxrq %u\n",
        Intqlen,Ibufsize,Iminfree,Ibuffail,Ibuf_max_rq);    /* g8fsl */
    }
示例#11
0
文件: kiss.c 项目: zidier215/tcpip
/* Perform device control on KISS TNC by sending control messages */
int32
kiss_ioctl(
struct iface *iface,
int cmd,
int set,
int32 val
){
	struct mbuf *hbp;
	uint8 *cp;
	int rval = 0;

	/* At present, only certain parameters are supported by
	 * stock KISS TNCs. As additional params are implemented,
	 * this will have to be edited
	 */
	switch(cmd){
	case PARAM_RETURN:
		set = 1;	/* Note fall-thru */
	case PARAM_TXDELAY:
	case PARAM_PERSIST:
	case PARAM_SLOTTIME:
	case PARAM_TXTAIL:
	case PARAM_FULLDUP:
	case PARAM_HW:
		if(!set){
			rval = -1;	/* Can't read back */
			break;
		}
		/* Allocate space for cmd and arg */
		if((hbp = alloc_mbuf(2)) == NULL){
			free_p(&hbp);
			rval = -1;
			break;
		}
		cp = hbp->data;
		*cp++ = cmd;
		*cp = val;
		hbp->cnt = 2;
		slip_raw(iface,&hbp);	/* Even more "raw" than kiss_raw */
		rval = val;		/* per Jay Maynard -- mce */
		break;
	case PARAM_SPEED:	/* These go to the local asy driver */
	case PARAM_DTR:
	case PARAM_RTS:
		rval = asy_ioctl(iface,cmd,set,val);
		break;
	default:		/* Not implemented */
		rval = -1;
		break;
	}
	return rval;
}
示例#12
0
文件: slip.c 项目: dieterdeyke/WAMPES
/* Send routine for point-to-point slip, no VJ header compression */
int
slip_send(
struct mbuf **bpp,      /* Buffer to send */
struct iface *iface,    /* Pointer to interface control block */
int32 gateway,          /* Ignored (SLIP is point-to-point) */
uint8 tos
){
	if(iface == NULL){
		free_p(bpp);
		return -1;
	}
	return (*iface->raw)(iface,bpp);
}
示例#13
0
文件: socket.c 项目: zidier215/tcpip
/* Low level send routine; user supplies mbuf for transmission. More
 * efficient than send() or sendto(), the higher level interfaces.
 * The "to" and "tolen" parameters are ignored on connection-oriented
 * sockets.
 *
 * In case of error, bp is freed so the caller doesn't have to worry about it.
 */
int
send_mbuf(
int s,			/* Socket index */
struct mbuf **bpp,	/* Buffer to send */
int flags,		/* not currently used */
struct sockaddr *to,		/* Destination, only for datagrams */
int tolen		/* Length of destination */
){
	register struct usock *up;
	int cnt;
	struct socklink *sp;

	if((up = itop(s)) == NULL){
		free_p(bpp);
		errno = EBADF;
		return -1;
	}
	sp = up->sp;
	/* Fail if send routine isn't present (shouldn't happen) */
	if(sp->send == NULL){
		free_p(bpp);
		return -1;
	}
	/* If remote address is supplied, check it */
	if(to != NULL && (sp->check != NULL)
	 && (*sp->check)(to,tolen) == -1){
		free_p(bpp);
		errno = EAFNOSUPPORT;
		return -1;
	}
	/* The proto send routine is expected to free the buffer
	 * we pass it even if the send fails
	 */
	if((cnt = (*sp->send)(up,bpp,to)) == -1){
		errno = EOPNOTSUPP;
		return -1;
	}
	return cnt;
}
示例#14
0
文件: ip.c 项目: zidier215/tcpip
/* Execute random quench algorithm on an interface's output queue */
void
rquench(
struct iface *ifp,
int drop
){
	struct mbuf *bp,*bplast;
	int i;
	struct qhdr qhdr;
	struct ip ip;
	struct mbuf *bpdup;

	if((i = len_q(ifp->outq)) == 0)
		return;	/* Queue is empty */

	i = urandom(i);	/* Select a victim */

	/* Search for i-th message on queue */
	bplast = NULL;
	for(bp = ifp->outq;bp != NULL && i>0;i--,bplast=bp,bp=bp->anext)
		;
	if(bp == NULL)
		return;	/* "Can't happen" */

	/* Send a source quench */
	dup_p(&bpdup,bp,0,len_p(bp));
	pullup(&bpdup,&qhdr,sizeof(qhdr));
	ntohip(&ip,&bpdup);
	icmp_output(&ip,bpdup,ICMP_QUENCH,0,NULL);
	free_p(&bpdup);
	if(!drop)
		return;	/* All done */

	/* Drop the packet */
	if(bplast != NULL)
		bplast->anext = bp->anext;
	else
		ifp->outq = bp->anext;	/* First on list */
	free_p(&bp);
}
示例#15
0
static void tcp_receive(struct tcb *tcb, int32 cnt)
{

  char buffer[1024];
  struct mbuf *bp;

  if (tcb->user > 0) {
    recv_tcp(tcb, &bp, 0);
    while ((cnt = pullup(&bp, buffer, sizeof(buffer))) > 0)
      if (write(tcb->user, buffer, (unsigned) cnt) != cnt) {
	free_p(&bp);
	close_tcp(tcb);
	return;
      }
  }
}
示例#16
0
文件: kiss.c 项目: zidier215/tcpip
/* Process incoming KISS TNC frame */
void
kiss_recv(
struct iface *iface,
struct mbuf **bpp
){
	char kisstype;

	kisstype = PULLCHAR(bpp);
	switch(kisstype & 0xf){
	case PARAM_DATA:
		ax_recv(iface,bpp);
		break;
	default:
		free_p(bpp);
		break;
	}
}
示例#17
0
文件: ip.c 项目: zidier215/tcpip
/* Create a fragment */
static struct frag *
newfrag(
uint16 offset,
uint16 last,
struct mbuf **bpp
){
	struct frag *fp;

	if((fp = (struct frag *)calloc(1,sizeof(struct frag))) == NULL){
		/* Drop fragment */
		free_p(bpp);
		return NULL;
	}
	fp->buf = *bpp;
	*bpp = NULL;
	fp->offset = offset;
	fp->last = last;
	return fp;
}
示例#18
0
文件: slip.c 项目: dieterdeyke/WAMPES
/* Send routine for point-to-point slip, with VJ header compression */
int
vjslip_send(
struct mbuf **bpp,      /* Buffer to send */
struct iface *iface,    /* Pointer to interface control block */
int32 gateway,          /* Ignored (SLIP is point-to-point) */
uint8 tos
){
	register struct slip *sp;
	int type;

	if(iface == NULL){
		free_p(bpp);
		return -1;
	}
	sp = &Slip[iface->xdev];
	/* Attempt IP/ICP header compression */
	type = slhc_compress(sp->slcomp,bpp,TRUE);
	(*bpp)->data[0] |= type;
	return (*iface->raw)(iface,bpp);
}
示例#19
0
文件: slip.c 项目: dieterdeyke/WAMPES
/* Encode a packet in SLIP format */
static
struct mbuf *
slip_encode(struct mbuf **bpp)
{
	struct mbuf *lbp;       /* Mbuf containing line-ready packet */
	register uint8 *cp;
	int c;

	/* Allocate output mbuf that's twice as long as the packet.
	 * This is a worst-case guess (consider a packet full of FR_ENDs!)
	 */
	lbp = alloc_mbuf(2*len_p(*bpp) + 2);
	if(lbp == NULL){
		/* No space; drop */
		free_p(bpp);
		return NULL;
	}
	cp = lbp->data;

	/* Flush out any line garbage */
	*cp++ = FR_END;

	/* Copy input to output, escaping special characters */
	while((c = PULLCHAR(bpp)) != -1){
		switch(c){
		case FR_ESC:
			*cp++ = FR_ESC;
			*cp++ = T_FR_ESC;
			break;
		case FR_END:
			*cp++ = FR_ESC;
			*cp++ = T_FR_END;
			break;
		default:
			*cp++ = c;
		}
	}
	*cp++ = FR_END;
	lbp->cnt = cp - lbp->data;
	return lbp;
}
示例#20
0
/* Dump packet bytes, no interpretation */
void
raw_dump(
struct iface *ifp,
int direction,
struct mbuf *bp)
{
	struct mbuf *tbp;
	FILE *fp;

	if((fp = ifp->trfp) == NULL)
		return;
	fprintf(fp,"\n******* raw packet dump (%s)\n",
	 ((direction & IF_TRACE_OUT) ? "send" : "recv"));
	dup_p(&tbp,bp,0,len_p(bp));
	if(tbp != NULL)
		hex_dump(fp,&tbp);
	else
		fprintf(fp,nospace);
	fprintf(fp,"*******\n");
	free_p(&tbp);
}
示例#21
0
static void tcp_send(struct tcb *tcb)
{

  int cnt;
  struct mbuf *bp;

  if ((cnt = space_tcp(tcb)) <= 0) {
    off_read(tcb->user);
    return;
  }
  if (!(bp = alloc_mbuf(cnt))) return;
  cnt = read(tcb->user, bp->data, (unsigned) cnt);
  if (cnt <= 0) {
    free_p(&bp);
    off_read(tcb->user);
    close_tcp(tcb);
    return;
  }
  bp->cnt = cnt;
  send_tcp(tcb, &bp);
}
示例#22
0
/* Size of the object pointed to by an untagged pointer */
template <typename Fixup> cell object::size(Fixup fixup) const {
  if (free_p())
    return ((free_heap_block*)this)->size();

  switch (type()) {
    case ARRAY_TYPE:
      return align(array_size((array*)this), data_alignment);
    case BIGNUM_TYPE:
      return align(array_size((bignum*)this), data_alignment);
    case BYTE_ARRAY_TYPE:
      return align(array_size((byte_array*)this), data_alignment);
    case STRING_TYPE:
      return align(string_size(string_capacity((string*)this)), data_alignment);
    case TUPLE_TYPE: {
      tuple_layout* layout = (tuple_layout*)fixup.translate_data(
          untag<object>(((tuple*)this)->layout));
      return align(tuple_size(layout), data_alignment);
    }
    case QUOTATION_TYPE:
      return align(sizeof(quotation), data_alignment);
    case WORD_TYPE:
      return align(sizeof(word), data_alignment);
    case FLOAT_TYPE:
      return align(sizeof(boxed_float), data_alignment);
    case DLL_TYPE:
      return align(sizeof(dll), data_alignment);
    case ALIEN_TYPE:
      return align(sizeof(alien), data_alignment);
    case WRAPPER_TYPE:
      return align(sizeof(wrapper), data_alignment);
    case CALLSTACK_TYPE:
      return align(
          callstack_object_size(untag_fixnum(((callstack*)this)->length)),
          data_alignment);
    default:
      critical_error("Invalid header in size", (cell)this);
      return 0; /* can't happen */
  }
}
示例#23
0
cell object::binary_payload_start(Fixup fixup) const
{
	if(free_p()) return 0;

	switch(type())
	{
	/* these objects do not refer to other objects at all */
	case FLOAT_TYPE:
	case BYTE_ARRAY_TYPE:
	case BIGNUM_TYPE:
	case CALLSTACK_TYPE:
		return 0;
	/* these objects have some binary data at the end */
	case WORD_TYPE:
		return sizeof(word) - sizeof(cell) * 3;
	case ALIEN_TYPE:
		return sizeof(cell) * 3;
	case DLL_TYPE:
		return sizeof(cell) * 2;
	case QUOTATION_TYPE:
		return sizeof(quotation) - sizeof(cell) * 2;
	case STRING_TYPE:
		return sizeof(string);
	/* everything else consists entirely of pointers */
	case ARRAY_TYPE:
		return array_size<array>(array_capacity((array*)this));
	case TUPLE_TYPE:
		{
			tuple_layout *layout = (tuple_layout *)fixup.translate_data(untag<object>(((tuple *)this)->layout));
			return tuple_size(layout);
		}
	case WRAPPER_TYPE:
		return sizeof(wrapper);
	default:
		critical_error("Invalid header in binary_payload_start",(cell)this);
		return 0; /* can't happen */
	}
}
示例#24
0
/* TCP garbage collection - called by storage allocator when free space
 * runs low. The send and receive queues are crunched. If the situation
 * is red, the resequencing queue is discarded; otherwise it is
 * also crunched.
 */
void
tcp_garbage(
int red)
{
	struct tcb *tcb;
	struct reseq *rp,*rp1;

	for(tcb = Tcbs;tcb != NULL;tcb = tcb->next){
		mbuf_crunch(&tcb->rcvq);
		mbuf_crunch(&tcb->sndq);
		for(rp = tcb->reseq;rp != NULL;rp = rp1){
			rp1 = rp->next;
			if(red){
				free_p(&rp->bp);
				free(rp);
			} else {
				mbuf_crunch(&rp->bp);
			}
		}
		if(red)
			tcb->reseq = NULL;
	}
}
示例#25
0
/* Close our TCB */
void
close_self(
struct tcb *tcb,
int reason)
{
	struct reseq *rp1;
	struct reseq *rp;

	if(tcb == NULL)
		return;

	stop_timer(&tcb->timer);
	tcb->reason = reason;

	/* Flush reassembly queue; nothing more can arrive */
	for(rp = tcb->reseq;rp != NULL;rp = rp1){
		rp1 = rp->next;
		free_p(&rp->bp);
		free(rp);
	}
	tcb->reseq = NULL;
	settcpstate(tcb,TCP_CLOSED);
}
示例#26
0
/* Process remote command */
static void
uremote(
    struct iface *iface,
    struct udp_cb *up,
    int cnt)
{

    struct mbuf *bp;
    struct socket fsock;
    char command;
    int32 addr;

    recv_udp(up,&fsock,&bp);
    command = PULLCHAR(&bp);
    switch(command & 0xff) {
    case SYS__EXIT:
        if(chkrpass(bp) == 0) {
            logmsg(NULL,"%s - Remote exit PASSWORD FAIL",
                   pinet_udp(&fsock));
        } else {
            logmsg(NULL,"%s - Remote exit PASSWORD OK",
                   pinet_udp(&fsock));
            main_exit = 1;
        }
        break;
    case KICK__ME:
        if(len_p(bp) >= sizeof(int32))
            addr = pull32(&bp);
        else
            addr = fsock.address;
        kick(addr);
        /*** smtptick((void *)addr); ***/
        break;
    }
    free_p(&bp);
}
示例#27
0
文件: slip.c 项目: dieterdeyke/WAMPES
/* Process incoming bytes in SLIP format
 * When a buffer is complete, return it; otherwise NULL
 */
static
struct mbuf *
slip_decode(
register struct slip *sp,
uint8 c)                /* Incoming character */
{
	struct mbuf *bp;

	switch(c){
	case FR_END:
		bp = sp->rbp_head;
		sp->rbp_head = NULL;
		if(sp->escaped){
			/* Treat this as an abort - discard frame */
			free_p(&bp);
			bp = NULL;
		}
		sp->escaped &= ~SLIP_FLAG;
		return bp;      /* Will be NULL if empty frame */
	case FR_ESC:
		sp->escaped |= SLIP_FLAG;
		return NULL;
	}
	if(sp->escaped & SLIP_FLAG){
		/* Translate 2-char escape sequence back to original char */
		sp->escaped &= ~SLIP_FLAG;
		switch(c){
		case T_FR_ESC:
			c = FR_ESC;
			break;
		case T_FR_END:
			c = FR_END;
			break;
		default:
			sp->errors++;
			break;
		}
	}
	/* We reach here with a character for the buffer;
	 * make sure there's space for it
	 */
	if(sp->rbp_head == NULL){
		/* Allocate first mbuf for new packet */
		if((sp->rbp_tail = sp->rbp_head = alloc_mbuf(SLIP_ALLOC)) == NULL)
			return NULL; /* No memory, drop */
		sp->rcp = sp->rbp_head->data;
	} else if(sp->rbp_tail->cnt == SLIP_ALLOC){
		/* Current mbuf is full; link in another */
		if((sp->rbp_tail->next = alloc_mbuf(SLIP_ALLOC)) == NULL){
			/* No memory, drop whole thing */
			free_p(&sp->rbp_head);
			sp->rbp_head = NULL;
			return NULL;
		}
		sp->rbp_tail = sp->rbp_tail->next;
		sp->rcp = sp->rbp_tail->data;
	}
	/* Store the character, increment fragment and total
	 * byte counts
	 */
	*sp->rcp++ = c;
	sp->rbp_tail->cnt++;
	return NULL;
}
示例#28
0
 cell stack_frame_size() const {
   if (free_p())
     return 0;
   return (header >> 20) & 0xFF0;
 }
示例#29
0
文件: ip.c 项目: zidier215/tcpip
/* Reassemble incoming IP fragments and dispatch completed datagrams
 * to the proper transport module
 */
void
ip_recv(
struct iface *iface,	/* Incoming interface */
struct ip *ip,		/* Extracted IP header */
struct mbuf **bpp,	/* Data portion */
int rxbroadcast,	/* True if received on subnet broadcast address */
int32 spi		/* Security association, if any */
){
	/* Function to call with completed datagram */
	register struct raw_ip *rp;
	struct mbuf *bp1;
	int rxcnt = 0;
	register struct iplink *ipp;

	/* If we have a complete packet, call the next layer
	 * to handle the result. Note that fraghandle passes back
	 * a length field that does NOT include the IP header
	 */
	if(bpp == NULL || fraghandle(ip,bpp) == -1)
		return;		/* Not done yet */

	/* Trim data segment if necessary. */
	trim_mbuf(bpp,ip->length - (IPLEN + ip->optlen));

	ipInDelivers++;
	if(Ip_trace)
		dumpip(iface,ip,*bpp,spi);

	for(rp = Raw_ip;rp != NULL;rp = rp->next){
		if(rp->protocol != ip->protocol)
			continue;
		rxcnt++;
		/* Duplicate the data portion, and put the header back on */
		dup_p(&bp1,*bpp,0,len_p(*bpp));
		if(bp1 != NULL){
			htonip(ip,&bp1,IP_CS_OLD);
			enqueue(&rp->rcvq,&bp1);
			if(rp->r_upcall != NULL)
				(*rp->r_upcall)(rp);
		} else {
			free_p(&bp1);
		}
	}
	/* Look it up in the transport protocol table */
	for(ipp = Iplink;ipp->funct != NULL;ipp++){
		if(ipp->proto == ip->protocol)
			break;
	}
	if(ipp->funct != NULL){
		/* Found, call transport protocol */
		(*ipp->funct)(iface,ip,bpp,rxbroadcast,spi);
	} else {
		/* Not found */
		if(rxcnt == 0){
			/* Send an ICMP Protocol Unknown response... */
			ipInUnknownProtos++;
			/* ...unless it's a broadcast */
			if(!rxbroadcast){
				icmp_output(ip,*bpp,ICMP_DEST_UNREACH,
				 ICMP_PROT_UNREACH,NULL);
			}
		}
		free_p(bpp);
	}
}
示例#30
0
文件: ip.c 项目: zidier215/tcpip
/* Process IP datagram fragments
 * If datagram is complete, return its length (MINUS header);
 * otherwise return -1
 */
static int
fraghandle(
struct ip *ip,		/* IP header, host byte order */
struct mbuf **bpp	/* The fragment itself */
){
	register struct reasm *rp; /* Pointer to reassembly descriptor */
	struct frag *lastfrag,*nextfrag,*tfp;
	struct mbuf *tbp;
	uint16 i;
	uint16 last;		/* Index of first byte beyond fragment */

	last = ip->offset + ip->length - (IPLEN + ip->optlen);

	rp = lookup_reasm(ip);
	if(ip->offset == 0 && !ip->flags.mf){
		/* Complete datagram received. Discard any earlier fragments */
		if(rp != NULL){
			free_reasm(rp);
			ipReasmOKs++;
		}
		return ip->length;
	}
	ipReasmReqds++;
	if(rp == NULL){
		/* First fragment; create new reassembly descriptor */
		if((rp = creat_reasm(ip)) == NULL){
			/* No space for descriptor, drop fragment */
			ipReasmFails++;
			free_p(bpp);
			return -1;
		}
	}
	/* Keep restarting timer as long as we keep getting fragments */
	stop_timer(&rp->timer);
	start_timer(&rp->timer);

	/* If this is the last fragment, we now know how long the
	 * entire datagram is; record it
	 */
	if(!ip->flags.mf)
		rp->length = last;

	/* Set nextfrag to the first fragment which begins after us,
	 * and lastfrag to the last fragment which begins before us
	 */
	lastfrag = NULL;
	for(nextfrag = rp->fraglist;nextfrag != NULL;nextfrag = nextfrag->next){
		if(nextfrag->offset > ip->offset)
			break;
		lastfrag = nextfrag;
	}
	/* Check for overlap with preceeding fragment */
	if(lastfrag != NULL  && ip->offset < lastfrag->last){
		/* Strip overlap from new fragment */
		i = lastfrag->last - ip->offset;
		pullup(bpp,NULL,i);
		if(*bpp == NULL)
			return -1;	/* Nothing left */
		ip->offset += i;
	}
	/* Look for overlap with succeeding segments */
	for(; nextfrag != NULL; nextfrag = tfp){
		tfp = nextfrag->next;	/* save in case we delete fp */

		if(nextfrag->offset >= last)
			break;	/* Past our end */
		/* Trim the front of this entry; if nothing is
		 * left, remove it.
		 */
		i = last - nextfrag->offset;
		pullup(&nextfrag->buf,NULL,i);
		if(nextfrag->buf == NULL){
			/* superseded; delete from list */
			if(nextfrag->prev != NULL)
				nextfrag->prev->next = nextfrag->next;
			else
				rp->fraglist = nextfrag->next;
			if(tfp->next != NULL)
				nextfrag->next->prev = nextfrag->prev;
			freefrag(nextfrag);
		} else
			nextfrag->offset = last;
	}
	/* Lastfrag now points, as before, to the fragment before us;
	 * nextfrag points at the next fragment. Check to see if we can
	 * join to either or both fragments.
	 */
	i = INSERT;
	if(lastfrag != NULL && lastfrag->last == ip->offset)
		i |= APPEND;
	if(nextfrag != NULL && nextfrag->offset == last)
		i |= PREPEND;
	switch(i){
	case INSERT:	/* Insert new desc between lastfrag and nextfrag */
		tfp = newfrag(ip->offset,last,bpp);
		tfp->prev = lastfrag;
		tfp->next = nextfrag;
		if(lastfrag != NULL)
			lastfrag->next = tfp;	/* Middle of list */
		else
			rp->fraglist = tfp;	/* First on list */
		if(nextfrag != NULL)
			nextfrag->prev = tfp;
		break;
	case APPEND:	/* Append to lastfrag */
		append(&lastfrag->buf,bpp);
		lastfrag->last = last;	/* Extend forward */
		break;
	case PREPEND:	/* Prepend to nextfrag */
		tbp = nextfrag->buf;
		nextfrag->buf = *bpp;
		bpp = NULL;
		append(&nextfrag->buf,&tbp);
		nextfrag->offset = ip->offset;	/* Extend backward */
		break;
	case (APPEND|PREPEND):
		/* Consolidate by appending this fragment and nextfrag
		 * to lastfrag and removing the nextfrag descriptor
		 */
		append(&lastfrag->buf,bpp);
		append(&lastfrag->buf,&nextfrag->buf);
		nextfrag->buf = NULL;
		lastfrag->last = nextfrag->last;

		/* Finally unlink and delete the now unneeded nextfrag */
		lastfrag->next = nextfrag->next;
		if(nextfrag->next != NULL)
			nextfrag->next->prev = lastfrag;
		freefrag(nextfrag);
		break;
	}
	if(rp->fraglist->offset == 0 && rp->fraglist->next == NULL 
		&& rp->length != 0){

		/* We've gotten a complete datagram, so extract it from the
		 * reassembly buffer and pass it on.
		 */
		*bpp = rp->fraglist->buf;
		rp->fraglist->buf = NULL;
		/* Tell IP the entire length */
		ip->length = rp->length + (IPLEN + ip->optlen);
		free_reasm(rp);
		ipReasmOKs++;
		ip->offset = 0;
		ip->flags.mf = 0;
		return ip->length;
	} else
		return -1;
}