/*------------------------------------------------------------------------
 *  mkarp  -  allocate and fill in an ARP or RARP packet
 *------------------------------------------------------------------------
 */
static
struct ep *
mkarp(int ifn, short type, short op, IPaddr spa, IPaddr tpa)
{
	register struct	arp	*parp;
	struct	ep		*pep;

	pep = (struct ep *) getbuf(Net.netpool);
	if ((int)pep == SYSERR)
		return (struct ep *)SYSERR;
	memcpy(pep->ep_dst, nif[ifn].ni_hwb.ha_addr, EP_ALEN);
	pep->ep_order = ~0;
	pep->ep_type = type;
	parp = (struct arp *)pep->ep_data;
	parp->ar_hwtype = hs2net(AR_HARDWARE);
	parp->ar_prtype = hs2net(EPT_IP);
	parp->ar_hwlen = EP_ALEN;
	parp->ar_prlen = IP_ALEN;
	parp->ar_op = hs2net(op);
	memcpy(SHA(parp), nif[ifn].ni_hwa.ha_addr, EP_ALEN);
	memcpy(SPA(parp), &spa, IP_ALEN);
	memcpy(THA(parp), nif[ifn].ni_hwa.ha_addr, EP_ALEN);
	memcpy(TPA(parp), &tpa, IP_ALEN);
	return pep;
}
Exemple #2
0
void
arp_print(netdissect_options *ndo,
	  const u_char *bp, u_int length, u_int caplen)
{
	const struct arp_pkthdr *ap;
	u_short pro, hrd, op, linkaddr;

	ap = (const struct arp_pkthdr *)bp;
	ND_TCHECK(*ap);

	hrd = HRD(ap);
	pro = PRO(ap);
	op = OP(ap);

        
        /* if its ATM then call the ATM ARP printer
           for Frame-relay ARP most of the fields
           are similar to Ethernet so overload the Ethernet Printer
           and set the linkaddr type for linkaddr_string() accordingly */

        switch(hrd) {
        case ARPHRD_ATM2225:
            atmarp_print(ndo, bp, length, caplen);
            return;
        case ARPHRD_FRELAY:
            linkaddr = LINKADDR_FRELAY;
            break;
        default:
            linkaddr = LINKADDR_ETHER;
            break;
	}

	if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) {
		ND_PRINT((ndo, "[|ARP]"));
		ND_DEFAULTPRINT((const u_char *)ap, length);
		return;
	}

        if (!ndo->ndo_eflag) {
            ND_PRINT((ndo, "ARP, "));
        }

        /* print hardware type/len and proto type/len */
        if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
	    PROTO_LEN(ap) != 4 ||
            HRD_LEN(ap) == 0 ||
            ndo->ndo_vflag) {
            ND_PRINT((ndo, "%s (len %u), %s (len %u)",
                      tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
                      HRD_LEN(ap),
                      tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
                      PROTO_LEN(ap)));

            /* don't know know about the address formats */
            if (!ndo->ndo_vflag) {
                goto out;
            }
	}

        /* print operation */
        printf("%s%s ",
               ndo->ndo_vflag ? ", " : "", 
               tok2str(arpop_values, "Unknown (%u)", op));

	switch (op) {

	case ARPOP_REQUEST:
		ND_PRINT((ndo, "who-has %s", ipaddr_string(TPA(ap))));
		if (memcmp((const char *)ezero, (const char *)THA(ap), HRD_LEN(ap)) != 0)
			ND_PRINT((ndo, " (%s)",
				  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap))));
		ND_PRINT((ndo, " tell %s", ipaddr_string(SPA(ap))));
		break;

	case ARPOP_REPLY:
		ND_PRINT((ndo, "%s is-at %s",
                          ipaddr_string(SPA(ap)),
                          linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
		break;

	case ARPOP_REVREQUEST:
		ND_PRINT((ndo, "who-is %s tell %s",
			  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
			  linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
		break;

	case ARPOP_REVREPLY:
		ND_PRINT((ndo, "%s at %s",
			  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
			  ipaddr_string(TPA(ap))));
		break;

	case ARPOP_INVREQUEST:
		ND_PRINT((ndo, "who-is %s tell %s",
			  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
			  linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
		break;

	case ARPOP_INVREPLY:
		ND_PRINT((ndo,"%s at %s",
			  linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
			  ipaddr_string(TPA(ap))));
		break;

	default:
		ND_DEFAULTPRINT((const u_char *)ap, caplen);
		return;
	}

 out:
        ND_PRINT((ndo, ", length %u", length));

	return;
trunc:
	ND_PRINT((ndo, "[|ARP]"));
}
void
arp_print(register const u_char *bp, u_int length, u_int caplen)
{
	register const struct ether_arp *ap;
	register const struct ether_header *eh;
	register u_short pro, hrd, op;

	ap = (struct ether_arp *)bp;
	if ((u_char *)(ap + 1) > snapend) {
		printf("[|arp]");
		return;
	}
	if (length < sizeof(struct ether_arp)) {
		(void)printf("truncated-arp");
		default_print((u_char *)ap, length);
		return;
	}

	pro = EXTRACT_16BITS(&ap->arp_pro);
	hrd = EXTRACT_16BITS(&ap->arp_hrd);
	op = EXTRACT_16BITS(&ap->arp_op);

	if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL)
	    || ap->arp_hln != sizeof(SHA(ap))
	    || ap->arp_pln != sizeof(SPA(ap))) {
		(void)printf("arp-#%d for proto #%d (%d) hardware #%d (%d)",
				op, pro, ap->arp_pln,
				hrd, ap->arp_hln);
		return;
	}
	if (pro == ETHERTYPE_TRAIL)
		(void)printf("trailer-");
	eh = (struct ether_header *)packetp;
	switch (op) {

	case ARPOP_REQUEST:
		(void)printf("arp who-has %s", ipaddr_string(TPA(ap)));
		if (memcmp((char *)ezero, (char *)THA(ap), 6) != 0)
			(void)printf(" (%s)", etheraddr_string(THA(ap)));
		(void)printf(" tell %s", ipaddr_string(SPA(ap)));
		if (memcmp((char *)ESRC(eh), (char *)SHA(ap), 6) != 0)
			(void)printf(" (%s)", etheraddr_string(SHA(ap)));
		break;

	case ARPOP_REPLY:
		(void)printf("arp reply %s", ipaddr_string(SPA(ap)));
		if (memcmp((char *)ESRC(eh), (char *)SHA(ap), 6) != 0)
			(void)printf(" (%s)", etheraddr_string(SHA(ap)));
		(void)printf(" is-at %s", etheraddr_string(SHA(ap)));
		if (memcmp((char *)EDST(eh), (char *)THA(ap), 6) != 0)
			(void)printf(" (%s)", etheraddr_string(THA(ap)));
		break;

	case REVARP_REQUEST:
		(void)printf("rarp who-is %s tell %s",
			etheraddr_string(THA(ap)),
			etheraddr_string(SHA(ap)));
		break;

	case REVARP_REPLY:
		(void)printf("rarp reply %s at %s",
			etheraddr_string(THA(ap)),
			ipaddr_string(TPA(ap)));
		break;

	default:
		(void)printf("arp-#%d", op);
		default_print((u_char *)ap, caplen);
		return;
	}
	if (hrd != ARPHRD_ETHER)
		printf(" hardware #%d", hrd);
}
Exemple #4
0
/* If no request is currently being processed and there's new requests in
   the queue, process the first one. This can be called from an interrupt
   or the normal kernel context. */
void do_request(blkreq_t *req)
{
    fd_dev_t *dev;
    u_long track, sect, cyl, head, big_sect, sects;
    u_long flags;
    int i;

    save_flags(flags);

    /* This label is used to eliminate tail-recursion. */
top:

    cli();
    if(current_req != NULL)
    {
	if(req != NULL)
	    append_node(&fd_reqs, &req->node);
	load_flags(flags);
	return;
    }
    for(i = 0; i < 2; i++)
    {
	if(fd_devs[i].recalibrate)
	{
	    fdc_recal(&fd_devs[i]);
	    if(req != NULL)
		append_node(&fd_reqs, &req->node);
	    load_flags(flags);
	    return;
	}
    }
    if(req == NULL)
    {
	if(!list_empty_p(&fd_reqs))
	{
	    req = (blkreq_t *)fd_reqs.head;
	    remove_node(&req->node);
	}
	else
	{
	    load_flags(flags);
	    return;
	}
    }
    current_req = req;
#if 0
    req->retries = 0;
#endif
    load_flags(flags);

    dev = REQ_FD_DEV(req);

    DB(("fd:do_request: req=%p drive=%d block=%d nblocks=%d cmd=%d buf=%p\n",
	req, dev->drvno, req->block, req->nblocks, req->command, req->buf));

    switch(req->command)
    {
    case FD_CMD_SEEK:	/* We wanna MOVE DA HEAD! */
        /* Do da seek. */
	if(fdc_seek(dev, req->block) == FALSE)
	{
		handle_error("FD_CMD_SEEK, seek");
		goto top;
		break;
	}

	/* Then Sense Interrupt Status */
	if(fdc_sense() == FALSE)
	{
		handle_error("FD_CMD_SEEK, fdc_sense");
		goto top;
		break;
	}

	/* and now we have to Read the ID */
	if(fdc_read_id(dev) == FALSE)
	{
		handle_error("FD_CMD_SEEK, read_id");
		goto top;
		break;
	}

        fd_end_request(0);
	req = NULL;
        goto top;

    case FD_CMD_TIMER:
	fd_end_request(0);
	req = NULL;
	goto top;
    }

    if(req->block >= dev->total_blocks)
    {
	kprintf("fd: Device %s (%p) doesn't have a block %d!\n",
		dev->name, dev, req->block);
	fd_end_request(-1);
	req = NULL;
	goto top;
    }

    big_sect = req->block;
    sects = req->nblocks;

    track = big_sect / dev->disk_p->sectors;
    sect = big_sect % dev->disk_p->sectors + 1;
    head = track % dev->disk_p->heads;
    cyl = track / dev->disk_p->heads;

    DB(("fd:do_request: cyl=%d sect=%d head=%d sects=%d\n", cyl, sect, head, sects));

    switch(req->command)
    {
    case FD_CMD_READ:	/* We wanna READ the floppy! */

#if 0
        fd_end_request(0);
	req = NULL;
        goto top;
#endif

	/* We need to seek to the right cylinder. */
	if(fdc_seek(dev, cyl) == FALSE)
	{
		handle_error("FD_CMD_READ, seek");
		goto top;
		break;
	}

	/* Then Sense Interrupt Status */
	if(fdc_sense() == FALSE)
	{
		handle_error("FD_CMD_READ, fdc_sense");
		goto top;
		break;
	}

	/* and now we have to Read the ID */
	if(fdc_read_id(dev) == FALSE)
	{
		handle_error("FD_CMD_READ, read_id");
		goto top;
		break;
	}

#define TPA(XX) ((u_long)TO_PHYSICAL(XX))

	/* Tell the DMA what to do, and hope for the best! */
	/* Should move this inside fdc, in fdc_read() i think */
	DMAbuf.Buffer = track_buf;
	DMAbuf.Page = (u_int8)((TPA(track_buf) >> 16) & 0xff);
	DMAbuf.Offset = (u_int16)(TPA(track_buf) & 0xffff);
	DMAbuf.Len = (u_int16)(dev->disk_p->sectors * dev->disk_p->heads *
		FD_SECTSIZ) - 1;
	DMAbuf.Chan = FLOPPY_DMA;
	kernel->setup_dma(&DMAbuf, DMA_READ);

	/* Now we issue a read command. */
	if(fdc_read(dev, cyl) == FALSE)
	{
		handle_error("FD_CMD_READ, read");
		goto top;
		break;
	}

	break;

    case FD_CMD_WRITE:	/* We wanna WRITE it too! */

        fd_end_request(0);
	req = NULL;
        goto top;

    default:
	kprintf("fd:do_request: Unknown command in fd_req, %d\n",
		req->command);
	fd_end_request(-1);
	req = NULL;
	goto top;
    }
}