Esempio n. 1
0
/**
 * Send a UDP packet across the network to a certain destination
 * @param udpptr Pointer to UDP control block
 * @param datalen Length of data to be sent
 * @param buf Data to be sent
 * @return OK if packet is sent properly, otherwise SYSERR
 */
syscall udpSend(struct udp *udpptr, ushort datalen, void *buf)
{
    struct packet *pkt;
    struct udpPkt *udppkt = NULL;
    int result;

    pkt = netGetbuf();
    if (SYSERR == (int)pkt)
    {
        return SYSERR;
    }

    /* Set the length of the packet and set the curr pointer back that 
     * length */
    pkt->len = UDP_HDR_LEN + datalen;
    /* Round the datalength to maintain word alignment */
    pkt->curr -= (3 + (ulong)(pkt->len)) & ~0x03;

    /* Set UDP header fields and fill the packet with the data */
    udppkt = (struct udpPkt *)(pkt->curr);
    udppkt->srcPort = hs2net(udpptr->localpt);
    udppkt->dstPort = hs2net(udpptr->remotept);
    udppkt->len = hs2net(pkt->len);
    udppkt->chksum = 0;

    /* Zero out the data buffer so empty space is padded with zeroes */
    bzero(udppkt->data, datalen);
    memcpy(udppkt->data, buf, datalen);

    /* Calculate UDP checksum (which happens to be the same as TCP's) */
    udppkt->chksum = udpChksum(pkt, UDP_HDR_LEN + datalen,
                               &(udpptr->localip), &(udpptr->remoteip));

    /* Send the UDP packet through IP */
    result = ipv4Send(pkt, &(udpptr->localip), &(udpptr->remoteip),
                      IPv4_PROTO_UDP);

    if (SYSERR == netFreebuf(pkt))
    {
        return SYSERR;
    }

    return result;
}
Esempio n. 2
0
static struct packet *makePkt(ushort localpt, ushort remotept,
                              struct netaddr *localip,
                              struct netaddr *remoteip, ushort datalen,
                              void *buf)
{
    struct packet *pkt;
    struct udpPkt *udppkt = NULL;

    pkt = netGetbuf();

    if (SYSERR == (int)pkt)
    {
        return (struct packet *)SYSERR;
    }

    /* Set the length of the packet and set the curr pointer back that 
     * length */
    pkt->len = UDP_HDR_LEN + datalen;
    /* Round the datalength to maintain word alignment */
    pkt->curr -= (3 + (ulong)(pkt->len)) & ~0x03;

    /* Set UDP header fields and fill the packet with the data */
    udppkt = (struct udpPkt *)(pkt->curr);
    udppkt->srcPort = hs2net(localpt);
    udppkt->dstPort = hs2net(remotept);
    udppkt->len = hs2net(pkt->len);
    udppkt->chksum = 0;

    /* Zero out the data buffer so empty space is padded with zeroes */
    bzero(udppkt->data, datalen);
    memcpy(udppkt->data, buf, datalen);

    udppkt->chksum = udpChksum(pkt, UDP_HDR_LEN + datalen,
                               localip, remoteip);

    return pkt;
}
Esempio n. 3
0
/**
 * Receive a UDP packet and place it in the UDP device's input buffer
 * @param pkt Incoming UDP packet
 * @param src Source address
 * @param dst Destination address
 * @return OK if UDP packet is received properly, otherwise SYSERR
 */
syscall udpRecv(struct packet *pkt, struct netaddr *src,
                struct netaddr *dst)
{
    struct udpPkt *udppkt;
    struct udp *udpptr;
    struct udpPkt *tpkt;
#ifdef TRACE_UDP
    char strA[20];
    char strB[20];
#endif                          /* TRACE_UDP */

    irqmask im;

    /* Point to the start of the UDP header */
    udppkt = (struct udpPkt *)pkt->curr;

    if (NULL == udppkt)
    {
        UDP_TRACE("Invalid UDP packet.");
        netFreebuf(pkt);
        return SYSERR;
    }

    /* Calculate checksum */
    if (0 != udpChksum(pkt, net2hs(udppkt->len), src, dst))
    {
        UDP_TRACE("Invalid UDP checksum.");
        netFreebuf(pkt);
        return SYSERR;
    }

    /* Convert UDP header fields to host order */
    udppkt->srcPort = net2hs(udppkt->srcPort);
    udppkt->dstPort = net2hs(udppkt->dstPort);
    udppkt->len = net2hs(udppkt->len);

    im = disable();

    /* Locate the UDP socket (device) for the UDP packet */
    udpptr = udpDemux(udppkt->dstPort, udppkt->srcPort, dst, src);

    if (NULL == udpptr)
    {
#ifdef TRACE_UDP
        UDP_TRACE("No UDP socket found for this UDP packet.");
        netaddrsprintf(strA, src);
        netaddrsprintf(strB, dst);
        UDP_TRACE("Source: %s:%d, Destination: %s:%d", strA,
                  udppkt->srcPort, strB, udppkt->dstPort);
#endif                          /* TRACE_UDP */
        restore(im);
        /* Send ICMP port unreachable message */
        icmpDestUnreach(pkt, ICMP_PORT_UNR);
        netFreebuf(pkt);
        return SYSERR;
    }
    if (udpptr->icount >= UDP_MAX_PKTS)
    {
        UDP_TRACE("UDP buffer is full. Dropping UDP packet.");
        restore(im);
        netFreebuf(pkt);
        return SYSERR;
    }

    /* Check "bind first" flag and update connection if set,
     * and clear the flag */
    if (UDP_FLAG_BINDFIRST & udpptr->flags)
    {
        udpptr->remotept = udppkt->srcPort;
        netaddrcpy(&(udpptr->localip), dst);
        netaddrcpy(&(udpptr->remoteip), src);
        udpptr->flags &= ~UDP_FLAG_BINDFIRST;
    }

    /* Get some buffer space to store the packet */
    tpkt = udpGetbuf(udpptr);

    if (SYSERR == (int)tpkt)
    {
        UDP_TRACE("Unable to get UDP buffer from pool. Dropping packet.");
        netFreebuf(pkt);
        return SYSERR;
    }

    /* Copy the data of the packet into the input buffer at the current 
     * position */
    memcpy(tpkt, udppkt, udppkt->len);

    /* Store the temporary UDP packet in a FIFO buffer */
    udpptr->in[(udpptr->istart + udpptr->icount) % UDP_MAX_PKTS] = tpkt;
    udpptr->icount++;

    restore(im);

    signal(udpptr->isem);

    netFreebuf(pkt);

    return OK;
}
Esempio n. 4
0
int
sendSyslog(uchar *syslogsrvr,char *msg, short port, int null)
{
	int	msglen;
	uchar *syslogmsg;
	ushort ip_len, sport;
	struct ether_header *enetp;
	struct ip *ipp;
	struct Udphdr *udpp;
	uchar	binip[8], binenet[8], *enetaddr;

	/* msglen is the length of the message, plus optionally the 
	 * terminating null character (-n option of syslog command)..
	 */
	msglen = strlen(msg) + null;

	/* Convert IP address to binary:
	 */
	if (IpToBin((char *)syslogsrvr,(unsigned char *)binip) < 0)
		return(0);

	/* Get the ethernet address for the IP:
	 */
	enetaddr = ArpEther(binip,binenet,0);
	if (!enetaddr) {
		printf("ARP failed for %s\n",syslogsrvr);
		return(0);
	}

	/* Retrieve an ethernet buffer from the driver and populate the
	 * ethernet level of packet:
	 */
	enetp = (struct ether_header *) getXmitBuffer();
	memcpy((char *)&enetp->ether_shost,(char *)BinEnetAddr,6);
	memcpy((char *)&enetp->ether_dhost,(char *)binenet,6);
	enetp->ether_type = ecs(ETHERTYPE_IP);

	/* Move to the IP portion of the packet and populate it
	 * appropriately:
	 */
	ipp = (struct ip *) (enetp + 1);
	ipp->ip_vhl = IP_HDR_VER_LEN;
	ipp->ip_tos = 0;
	ip_len = sizeof(struct ip) + sizeof(struct Udphdr) + msglen;
	ipp->ip_len = ecs(ip_len);
	ipp->ip_id = ipId();
	ipp->ip_off = 0;
	ipp->ip_ttl = UDP_TTL;
	ipp->ip_p = IP_UDP;
	memcpy((char *)&ipp->ip_src.s_addr,(char *)BinIpAddr,4);
	memcpy((char *)&ipp->ip_dst.s_addr,(char *)binip,4);

	/* Now UDP...
	 */
	sport = port+1;
	udpp = (struct Udphdr *) (ipp + 1);
	udpp->uh_sport = ecs(sport);
	udpp->uh_dport = ecs(port);
	udpp->uh_ulen = ecs((ushort)(ip_len - sizeof(struct ip)));

	/* Finally, the SYSLOG data ...
	 */
	syslogmsg = (uchar *)(udpp+1);
	strcpy((char *)syslogmsg,(char *)msg);

	ipChksum(ipp);			/* Compute csum of ip hdr */
	udpChksum(ipp);			/* Compute UDP checksum */

	sendBuffer(ETHERSIZE + IPSIZE + UDPSIZE + msglen);
	return(0);
}
Esempio n. 5
0
/* processGDB():
 * This is the function that allows a remote gdb host to connect to
 * the monitor with gdb at the udp level.  The connection command in
 * gdb to do this is:
 *
 *	target remote udp:TARGET_IP:TARGET_PORT
 */
int
processGDB(struct ether_header *ehdr,ushort size)
{
	char	*gdbp;
	struct	ip *ihdr, *ti, *ri;
	struct	Udphdr *uhdr, *tu, *ru;
	struct	ether_header *te;

	/* If SHOW_GDB is set (via ether -vg), then we dump the trace to
	 * the console; otherwise, we use mtrace.
	 */
#if INCLUDE_ETHERVERBOSE
	if (EtherVerbose & SHOW_GDB)
		gdbTrace = printf;
	else
#endif
		gdbTrace = Mtrace;

	ihdr = (struct ip *)(ehdr + 1);
	uhdr = (struct Udphdr *)((char *)ihdr + IP_HLEN(ihdr));
	gdbp = (char *)(uhdr + 1);
	size = ecs(uhdr->uh_ulen) - sizeof(struct Udphdr);

	/* Check for ACK/NAK here:
	 */
	if (size == 1) {
		if ((*gdbp == '+') || (*gdbp == '-')) {
			gdbTrace("GDB_%s\n",*gdbp == '+' ? "ACK" : "NAK");
			return(0);
		}
	}

	/* Copy the incoming udp payload (the gdb command) to gdbIbuf[]
	 * and NULL terminate it...
	 */
	memcpy((char *)gdbIbuf,(char *)gdbp,size);
	gdbIbuf[size] = 0;

	/* Now that we've stored away the GDB command request, we
	 * initially respond with the GDB acknowledgement ('+')...
	 */
	te = EtherCopy(ehdr);
	ti = (struct ip *) (te + 1);
	ri = (struct ip *) (ehdr + 1);
	ti->ip_vhl = ri->ip_vhl;
	ti->ip_tos = ri->ip_tos;
	ti->ip_len = ecs((1 + (sizeof(struct ip) + sizeof(struct Udphdr))));
	ti->ip_id = ipId();
	ti->ip_off = ri->ip_off;
	ti->ip_ttl = UDP_TTL;
	ti->ip_p = IP_UDP;
	memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr,
		sizeof(struct in_addr));
	memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr),
		sizeof(struct in_addr));
	tu = (struct Udphdr *) (ti + 1);
	ru = (struct Udphdr *) (ri + 1);
	tu->uh_sport = ru->uh_dport;
	tu->uh_dport = ru->uh_sport;
	tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + 1));
	gdbp = (char *)(tu+1);
	*gdbp = '+';

	ipChksum(ti);		/* Compute checksum of ip hdr */
	udpChksum(ti);		/* Compute UDP checksum */

	sendBuffer(sizeof(struct ether_header) + sizeof(struct ip) + 
		sizeof(struct Udphdr) + 1);

	/* Wrap the processing of the incoming packet with a set/clear
	 * of the gdbUdp flag so that the other gdb code can act 
	 * accordingly.
	 */
	gdbUdp = 1;
	if (gdb_cmd(gdbIbuf) == 0) {
		gdbUdp = 0;
		return(0);
	}
	gdbUdp = 0;

	/* Add 1 to the gdbRlen to include the NULL termination.
	 */
	gdbRlen++;	


	/* The second respons is only done if gdb_cmd returns non-zero.
	 * It is the response to the gdb command issued by the debugger
	 * on the host.
	 */
	te = EtherCopy(ehdr);
	ti = (struct ip *) (te + 1);
	ri = (struct ip *) (ehdr + 1);
	ti->ip_vhl = ri->ip_vhl;
	ti->ip_tos = ri->ip_tos;
	ti->ip_len = ecs((gdbRlen + (sizeof(struct ip) + sizeof(struct Udphdr))));
	ti->ip_id = ipId();
	ti->ip_off = ri->ip_off;
	ti->ip_ttl = UDP_TTL;
	ti->ip_p = IP_UDP;
	memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr,
		sizeof(struct in_addr));
	memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr),
		sizeof(struct in_addr));

	tu = (struct Udphdr *) (ti + 1);
	ru = (struct Udphdr *) (ri + 1);
	tu->uh_sport = ru->uh_dport;
	tu->uh_dport = ru->uh_sport;
	tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + gdbRlen));
	memcpy((char *)(tu+1),(char *)gdbRbuf,gdbRlen);

	ipChksum(ti);		/* Compute checksum of ip hdr */
	udpChksum(ti);		/* Compute UDP checksum */

	sendBuffer(sizeof(struct ether_header) + sizeof(struct ip) + 
		sizeof(struct Udphdr) + gdbRlen);

	return(1);
}
Esempio n. 6
0
/* BOOTPStartup()
 *	The DHCPDISCOVER is issued as an ethernet broadcast.  IF the bootp
 *	flag is non-zero then just do a bootp request (a subset of the 
 *	DHCPDISCOVER stuff).
 */
int
BOOTPStartup(short seconds)
{
	struct	dhcphdr *dhcpdata;
	struct	bootphdr *bootpdata;
	struct	ether_header *te;
	struct	ip *ti;
	struct	Udphdr *tu;
	ushort	uh_ulen;
	int		optlen;

	/* Retrieve an ethernet buffer from the driver and populate the
	 * ethernet level of packet:
	 */
	te = (struct ether_header *) getXmitBuffer();
	memcpy((char *)&te->ether_shost,(char *)BinEnetAddr,6);
	memcpy((char *)&te->ether_dhost,(char *)BroadcastAddr,6);
	te->ether_type = ecs(ETHERTYPE_IP);

	/* Move to the IP portion of the packet and populate it appropriately: */
	ti = (struct ip *) (te + 1);
	ti->ip_vhl = IP_HDR_VER_LEN;
	ti->ip_tos = 0;
	ti->ip_id = 0;
	ti->ip_off = ecs(0x4000);	/* No fragmentation allowed */
	ti->ip_ttl = UDP_TTL;
	ti->ip_p = IP_UDP;
	memset((char *)&ti->ip_src.s_addr,0,4);
	memset((char *)&ti->ip_dst.s_addr,0xff,4);

	/* Now udp... */
	tu = (struct Udphdr *) (ti + 1);
	tu->uh_sport = ecs(DhcpClientPort);
	tu->uh_dport = ecs(DhcpServerPort);

	/* First the stuff that is the same for BOOTP or DHCP... */
	bootpdata = (struct bootphdr *)(tu+1);
	dhcpdata = (struct dhcphdr *)(tu+1);
	dhcpdata->op = DHCPBOOTP_REQUEST;
	dhcpdata->htype = 1;
	dhcpdata->hlen = 6;
	dhcpdata->hops = 0;
	dhcpdata->seconds = ecs(seconds);
	memset((char *)dhcpdata->bootfile,0,
		sizeof(dhcpdata->bootfile));
	memset((char *)dhcpdata->server_hostname,0,
		sizeof(dhcpdata->server_hostname));

	/* For the first request issued, establish a transaction id based
	 * on a crc32 of the mac address.  For each request after that,
	 * just increment.
	 */
	if (!BOOTPTransactionId)
		BOOTPTransactionId = BinEnetAddr[5];
	else
		BOOTPTransactionId++;

	memcpy((char *)&dhcpdata->transaction_id,(char *)&BOOTPTransactionId,4);
	memset((char *)&dhcpdata->client_ip,0,4);
	memset((char *)&dhcpdata->your_ip,0,4);
	memset((char *)&dhcpdata->server_ip,0,4);
	memset((char *)&dhcpdata->router_ip,0,4);
	memcpy((char *)dhcpdata->client_macaddr,(char *)BinEnetAddr,6);
	dhcpdata->flags = 0;

	self_ecs(dhcpdata->flags);

	/* Finally, the DHCP or BOOTP specific stuff...
	 * Based on RFC1534 (Interoperation Between DHCP and BOOTP), any message
	 * received by a DHCP server that contains a 'DHCP_MESSAGETYPE' option
	 * is assumed to have been sent by a DHCP client.  A message without the
	 * DHCP_MESSAGETYPE option is assumed to have been sent by a BOOTP
	 * client.
	 */
	uh_ulen = optlen = 0;
	memset((char *)bootpdata->vsa,0,sizeof(bootpdata->vsa));
	uh_ulen = sizeof(struct Udphdr) + sizeof(struct bootphdr);
	tu->uh_ulen = ecs(uh_ulen);
	ti->ip_len = ecs((sizeof(struct ip) + uh_ulen));

	ipChksum(ti);	/* Compute checksum of ip hdr */
	udpChksum(ti);	/* Compute UDP checksum */

	DHCPState = BOOTPSTATE_REQUEST;
	sendBuffer(BOOTPSIZE);

	return(0);
}