arpcache.c 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ARPCACHE_C
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include <string.h>
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "Common.h"
#include "XCore.h"
#include "XNutOS.h"
#include "if_var.h"
#include "if_ether.h"
#include "inet.h"
#ifdef NUTDEBUG
#include "netdebug.h"
#endif
#if 0
/* Use for local debugging. */
#define NUTDEBUG
#include <stdio.h>
#define __tcp_trs stdout
static u_char __tcp_trf = 1;
#endif
#if defined(NUTNET)
/******************************************************************************
* *
* L O C A L D E F I N E S *
* *
******************************************************************************/
/*! \brief Maximum age of an entry in the ARP cache in minutes.
*
* Outdated entries will be regularly removed, forcing the Ethernet
* interface to generate new ARP requests. This way MAC address
* changes are detected.
*
* \showinitializer
*/
#ifndef MAX_ARPAGE
#define MAX_ARPAGE 9
#endif
/*! \brief Maximum number of ARP requests generated per query.
*
* If no ARP response is received after sending out the specified
* number of request, the related IP address is considered unreachable.
*
* \showinitializer
*/
#ifndef MAX_ARPREQUESTS
#define MAX_ARPREQUESTS 1
#endif
/*! \brief Minimum wait before sending out a new ARP request.
*
* The specified number of milliseconds will be doubled on each retry.
*
* \showinitializer
*/
#ifndef MIN_ARPWAIT
#define MIN_ARPWAIT 500
#endif
/******************************************************************************
* *
* L O C A L T Y P E D E F S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L I N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L U N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Remove all entries marked for removal.
*
* \param ifn The network interface.
*/
static void ArpCacheFlush(IFNET * ifn)
{
ARPENTRY *ae = ifn->arpTable;
ARPENTRY **aep = &ifn->arpTable;
while (ae) {
if (ae->ae_flags & ATF_REM) {
/* Remove all waiting threads from the queue of this
entry, but do not give up the CPU. If some other
thread takes over and deals with ARP, we are dead. */
NutEventBroadcastAsync(&ae->ae_tq);
#ifdef NUTDEBUG
if (__tcp_trf) {
fprintf(__tcp_trs, "[ARP-DEL %s]", inet_ntoa(ae->ae_ip));
}
#endif
*aep = ae->ae_next;
NutHeapFree(ae);
ae = *aep;
} else {
aep = &ae->ae_next;
ae = ae->ae_next;
}
}
}
/*!
* \brief Update the age of all ARP entries of all Ethernet devices.
*
* Increments the age of all ARP entries. Any entry with an age above
* \ref MAX_ARPAGE will be removed.
*
* If less less than one minute elapsed since the last update, the
* routine will return without updating any entry.
*/
static void ArpCacheAging(void)
{
static u_long last_update;
NUTDEVICE *dev;
if (NutGetSeconds() - last_update >= 60) {
last_update = NutGetSeconds();
/*
* Loop through the list of all registered devices.
*/
for (dev = nutDeviceList; dev; dev = dev->dev_next) {
/* Process network devices only. */
if (dev->dev_type == IFTYP_NET) {
IFNET *ifn = dev->dev_icb;
/* Process Ethernet interfaces only. */
if (ifn && ifn->if_type == IFT_ETHER) {
ARPENTRY *ae;
u_char rmf = 0;
/* Loop through all ARP entries of this interface. */
for (ae = ifn->arpTable; ae; ae = ae->ae_next) {
if ((ae->ae_flags & ATF_PERM) == 0 && /* Not permanent. */
ae->ae_outdated++ >= MAX_ARPAGE) { /* Outdated. */
ae->ae_flags |= ATF_REM;
}
rmf |= ae->ae_flags;
#ifdef NUTDEBUG
if (__tcp_trf) {
fprintf(__tcp_trs, "[ARP-AGE %s %u]", /* */
inet_ntoa(ae->ae_ip), ae->ae_outdated);
}
#endif
}
if (rmf & ATF_REM) {
ArpCacheFlush(ifn);
}
}
}
}
}
}
/*!
* \brief Locate an interface's ARP entry for a given IP address.
*
* \param ifn Pointer to the network interface.
* \param ip IP address to search, given in network byte order.
*
* \return Pointer to the ARP cache entry, if found, or NULL if no
* entry exists.
*/
static ARPENTRY *ArpCacheLookup(IFNET * ifn, u_long ip)
{
ARPENTRY *entry;
for (entry = ifn->arpTable; entry; entry = entry->ae_next) {
if (entry->ae_ip == ip)
break;
}
return entry;
}
/*!
* \brief Create a new entry in the interface's ARP cache.
*
* The new entry is added on top of the cache list.
*
* \param ifn Pointer to the network interface.
* \param ip IP address of the new entry, given in network byte order.
* \param ha Pointer to the MAC address. If NULL, an incomplete entry
* will be created.
*
* \return Pointer to the new entry or NULL if not enough memory is
* available.
*/
static ARPENTRY *ArpCacheNew(IFNET * ifn, u_long ip, u_char * ha)
{
ARPENTRY *entry;
/* Remove outdated entries before adding a new one. */
ArpCacheAging();
if ((entry = NutHeapAlloc(sizeof(ARPENTRY))) != 0) {
memset(entry, 0, sizeof(ARPENTRY));
entry->ae_ip = ip;
if (ha) {
memcpy(entry->ae_ha, ha, 6);
entry->ae_flags = ATF_COM;
}
entry->ae_next = ifn->arpTable;
ifn->arpTable = entry;
#ifdef NUTDEBUG
if (__tcp_trf) {
fprintf(__tcp_trs, "\n[ARP-NEW %s", inet_ntoa(ip));
if (ha) {
fprintf(__tcp_trs, " %02x%02x%02x%02x%02x%02x", /* */
ha[0], ha[1], ha[2], ha[3], ha[4], ha[5]);
}
fputc(']', __tcp_trs);
}
#endif
}
return entry;
}
/*!
* \brief Update an ARP entry.
*
* If an entry with the same IP address exists, then this entry is
* updated. If no entry exists, a new one is created. All threads
* waiting for address resolution are woken up.
*
* \note This function is automatically called on each incoming
* ARP telegram. Applications typically do not call this
* function.
*
* \param dev Identifies the device.
* \param ip Requested IP address in network byte order.
* \param ha Pointer to a buffer which receives the MAC address.
*
*/
void NutArpCacheUpdate(NUTDEVICE * dev, u_long ip, u_char * ha)
{
ARPENTRY *entry;
/*
* If an entry with this IP exists, wake up waiting threads. If the
* entry is not permanent, then update it and mark it completed first.
*/
if ((entry = ArpCacheLookup(dev->dev_icb, ip)) != 0) {
#ifdef NUTDEBUG
if (__tcp_trf) {
fprintf(__tcp_trs, "[ARP-UPD %s", inet_ntoa(ip));
if (ha) {
fprintf(__tcp_trs, " %02x%02x%02x%02x%02x%02x", /* */
ha[0], ha[1], ha[2], ha[3], ha[4], ha[5]);
}
fputc(']', __tcp_trs);
}
#endif
if ((entry->ae_flags & ATF_PERM) == 0) {
entry->ae_outdated = 0;
memcpy(entry->ae_ha, ha, 6);
entry->ae_flags |= ATF_COM;
}
NutEventBroadcast(&entry->ae_tq);
}
/*
* If no entry with this IP exists, then create a new completed one.
*/
else {
ArpCacheNew(dev->dev_icb, ip, ha);
}
}
/*!
* \brief Query MAC address for a specified IP address.
*
* If no entry is available in the ARP cache, an incomplete entry is
* created and ARP requests are generated on increasing time intervals.
* The calling thread is suspended until a matching ARP response is
* received or until a number of requests have been generated without
* receiving a response.
*
* \note This function is automatically called on each outgoing
* IP packet. Applications typically do not call this function.
*
* \param dev Identifies the device.
* \param ip IP address of which the caller asked the MAC address.
* \param mac Buffer for the retrieved MAC address.
*
* \return 0 if address resolved, -1 otherwise.
*/
int NutArpCacheQuery(NUTDEVICE * dev, CONST u_long ip, u_char * mac)
{
int rc = -1;
ARPENTRY *entry;
IFNET *ifn = dev->dev_icb;
NETBUF *nb = 0;
u_char retries = MAX_ARPREQUESTS;
u_long tmo = MIN_ARPWAIT;
/* Aging the cache on each query adds some processing to the path
* which we want to be as fast as possible. But when calling this
* function in NutArpCacheNew only, we will never detect when a
* node changes its MAC address. Anyway, the previous solution of
* running a timer thread consumed too much RAM.
*/
ArpCacheAging();
/*
* Search a matching entry. If none exists, create a new incomplete
* entry and a request packet. If another thread has entered this
* routine, an incomplete entry exists and the current thread will
* not create a request packet and send out requests.
*/
if ((entry = ArpCacheLookup(ifn, ip)) == 0) {
if ((entry = ArpCacheNew(ifn, ip, 0)) == 0) {
return -1;
}
if ((nb = NutArpAllocNetBuf(ARPOP_REQUEST, ip, 0)) == 0) {
entry->ae_flags |= ATF_REM;
ArpCacheFlush(ifn);
return -1;
}
}
/*
* We enter a loop, which will send ARP requests on increasing
* time intervals until our ARP entry gets completed. Give up
* after a configured number of retries.
*/
for (;;) {
/* If completed, provide the MAC address and exit. */
if (entry->ae_flags & ATF_COM) {
//Work around for GCC 3.4.3 bug #18251
//memcpy(mac, entry->ae_ha, 6);
//rc = 0;
rc = 6;
do {
rc--;
mac[rc] = entry->ae_ha[rc];
} while(rc);
break;
}
#ifdef NUTDEBUG
if (__tcp_trf) {
fprintf(__tcp_trs, "[%u.ARP-%s %s]", /* */
MAX_ARPREQUESTS - retries + 1, /* */
nb ? "QRY" : "WAIT", /* */
inet_ntoa(ip));
}
#endif
/* Give up on too many retries. */
if (retries-- == 0) {
break;
}
/* Mark buffer released and remove incomplete entry on transmit errors. */
if (nb && NutArpOutput(dev, nb)) {
nb = 0;
/* Even if the transmit failed, we may have received a response in the meantime. */
if ((entry = ArpCacheLookup(ifn, ip)) != NULL && (entry->ae_flags & ATF_COM) == 0) {
entry->ae_flags |= ATF_REM;
ArpCacheFlush(ifn);
}
break;
}
/* Sleep until woken up by an update of this ARP entry
or until timeout. Double the timeout on each retry. */
NutEventWait(&entry->ae_tq, tmo);
tmo += tmo;
/* During our sleep, another thread, which created the
incomplete entry, may have given up and removed the entry.
In this case we should also return an error. */
if ((entry = ArpCacheLookup(ifn, ip)) == 0) {
break;
}
}
/* Only the thread that created the entry, allocated a request
packet. If this thread fails, it should also remove the entry. */
if (nb) {
NutNetBufFree(nb);
/* Play save and check, if the entry still exists. */
if (rc && entry) {
entry->ae_flags |= ATF_REM;
ArpCacheFlush(ifn);
}
}
return rc;
}
#endif
arpin.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ARPIN_C
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "Common.h"
#include "XCore.h"
#include "if_var.h"
#include "if_ether.h"
#include "in.h"
#if defined(NUTNET)
/******************************************************************************
* *
* L O C A L D E F I N E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L T Y P E D E F S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L I N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L U N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Handle incoming ARP packets.
*
* Packets not destined to us or packets with unsupported
* address type or item length are silently discarded.
*
* \note This routine is called by the Ethernet layer on
* incoming ARP packets. Applications typically do
* not call this function.
*
* \param dev Identifies the device that received the packet.
* \param nb Pointer to a network buffer structure containing
* the ARP packet.
*/
void NutArpInput(NUTDEVICE * dev, NETBUF * nb)
{
ETHERARP *ea;
ARPHDR *ah;
IFNET *nif;
if (nb->nb_nw.sz < sizeof(ETHERARP)) {
NutNetBufFree(nb);
return;
}
ea = (ETHERARP *) nb->nb_nw.vp;
ah = (ARPHDR *) & ea->ea_hdr;
/*
* Silently discard packets with unsupported
* address types and lengths.
*/
if (ntohs(ah->ar_hrd) != ARPHRD_ETHER ||
ntohs(ah->ar_pro) != ETHERTYPE_IP ||
ah->ar_hln != 6 || ah->ar_pln != 4) {
NutNetBufFree(nb);
return;
}
/*
* Silently discard packets for other destinations.
*/
nif = dev->dev_icb;
if (ea->arp_tpa != nif->if_local_ip) {
NutNetBufFree(nb);
return;
}
/*
* TODO: Silently discard packets with our own
* source address.
*/
/*
* TODO: Discard packets with broadcast source
* address.
*/
/*
* TODO: Discard packets if source IP address
* equals our address. We should send a reply.
*/
/*
* Add the sender to our arp cache. Note, that we don't do
* this with replies only, but also with requests on our
* address. The assumption is that if someone is requesting
* our address, they are probably intending to talk to us,
* so it saves time if we cache their address.
*/
NutArpCacheUpdate(dev, ea->arp_spa, ea->arp_sha);
/*
* Reply to ARP requests.
*/
if (htons(ea->ea_hdr.ar_op) == ARPOP_REQUEST) {
NETBUF *nbr =
NutArpAllocNetBuf(ARPOP_REPLY, ea->arp_spa, ea->arp_sha);
if (nbr) {
if (!NutArpOutput(dev, nbr))
NutNetBufFree(nbr);
}
}
NutNetBufFree(nb);
}
#endif
arpout.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ARPOUT_C
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include <string.h>
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "Common.h"
#include "XCore.h"
#include "XNutOS.h"
#include "if_var.h"
#include "if_ether.h"
#include "ether.h"
#include "in.h"
#if defined(NUTNET)
/******************************************************************************
* *
* L O C A L D E F I N E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L T Y P E D E F S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L I N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L U N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Allocate an ARP network buffer structure.
*
* \param type Type of ARP packet.
* \param ip Target IP address.
* \param mac Target MAC address, null pointer for broadcast.
*
* \return Pointer to the allocated network buffer structure
* or 0 on failure.
*/
NETBUF *NutArpAllocNetBuf(u_short type, u_long ip, u_char * mac)
{
NETBUF *nb;
ETHERARP *ea;
ARPHDR *ah;
if ((nb = NutNetBufAlloc(0, NBAF_NETWORK, sizeof(ETHERARP))) == 0)
return 0;
ea = nb->nb_nw.vp;
ah = (ARPHDR *) & ea->ea_hdr;
/*
* Set ARP header.
*/
ah->ar_hrd = htons(ARPHRD_ETHER);
ah->ar_pro = htons(ETHERTYPE_IP);
ah->ar_hln = 6;
ah->ar_pln = 4;
ah->ar_op = htons(type);
/*
* Set ARP destination data.
*/
if (mac)
memcpy(ea->arp_tha, mac, 6);
else
memset(ea->arp_tha, 0xff, 6);
ea->arp_tpa = ip;
return nb;
}
/*!
* \brief Send an ARP packet.
*
* \note Applications typically do not call this function.
*
* \param dev Identifies the device to use.
* \param nb Network buffer structure containing the packet to be sent.
* The structure must have been allocated by a previous
* call NutNetBufAlloc().
*
* \return 0 on success, -1 in case of any errors.
*/
int NutArpOutput(NUTDEVICE * dev, NETBUF * nb)
{
ETHERARP *ea;
IFNET *nif;
ea = nb->nb_nw.vp;
/*
* Set ARP source data.
*/
nif = dev->dev_icb;
memcpy(ea->arp_sha, nif->if_mac, 6);
ea->arp_spa = nif->if_local_ip;
return (*nif->if_output)(dev, ETHERTYPE_ARP, ea->arp_tha, nb);
}
#endif
confnet.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define CONFNET_C
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include <string.h>
#include <time.h>
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "Common.h"
#include "XCore.h"
#include "XVarBank.h"
#include "XADC.h"
#include "inet.h"
#include "confnet.h"
#if defined(NUTNET)
/******************************************************************************
* *
* L O C A L D E F I N E S *
* *
******************************************************************************/
#define DEF_OUI {0x00,0x1B,0x82}
/******************************************************************************
* *
* L O C A L T Y P E D E F S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L I N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L U N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Random number generator.
*
* \return Random number between 0 and (num-1).
*/
static int NutNetRandom(int num)
{
int bit = 0, acc = 0, multi = 0;
int i;
for ( i = 0 ; i < 0x8 ; i++ )
{
StartADConvert(i);
acc += ReadAD(i);
bit |= ((acc & 0x1) << i);
multi *= bit;
}
//debug_printf("%s:%d\n", __FUNCTION__,i);
return ((bit + acc + multi) % num);
}
/*!
* \brief Return the unique Ethernet MAC address.
*
* \return Pointer to the MAC
*/
u_char *NutNetGetMAC(void)
{
_PrintRecord *prnrec = GrabPrintRecord();
static const u_char oui[3] = DEF_OUI;
static u_char mac[6];
/*
* Load the unique Ethernet MAC
*/
memcpy(mac, prnrec->UniqueMAC, sizeof(mac));
/*
* Is it the effective MAC ?
*/
if (memcmp(mac, oui, 3) != 0) {
/*
* Produce MAC at random
*/
memcpy(mac, oui, 3);
mac[3] = (u_char)0xFF;
mac[4] = (u_char)time(_NULL);
mac[5] = (u_char)NutNetRandom(0x100);
/*
* Restore the unique Ethernet MAC
*/
memcpy(prnrec->UniqueMAC, mac, sizeof(prnrec->UniqueMAC));
}
return (u_char *)mac;
}
/*!
* \brief The port number that the printer should use for it's RAW data.
*
* \return Base raw port number
*/
u_short NutNetGetPort(void)
{
_PrintCfg *prncfg = GrabPrintConfig();
return (u_short)prncfg->NetRawPort;
}
/*!
* \brief Load network configuration from non-volatile memory.
*
* If no configuration is available in EEPROM, all configuration
* parameters are cleared to zero. Except the MAC address, which
* is set to the Ethernet broadcast address.
*
* \param name Name of the device.
*
* \return 0 if configuration has been read. Otherwise the
* return value is -1.
*/
int NutNetLoadConfig(CONST char *name)
{
_PrintCfg *prncfg = GrabPrintConfig();
confnet = prncfg->confnet;
if (confnet.cd_size == sizeof(CONFNET) && strcmp(confnet.cd_name, name) == 0) {
return 0;
}
memset(&confnet, 0, sizeof(confnet));
/*
* Set initial MAC address to broadcast. Thanks to Tomohiro
* Haraikawa, who pointed out that all zeroes is occupied by
* Xerox and should not be used.
*/
memset(confnet.cdn_mac, 0xFF, sizeof(confnet.cdn_mac));
return -1;
}
/*!
* \brief Save network configuration in non-volatile memory.
*
* \return 0 if OK, -1 on failures.
*/
int NutNetSaveConfig(void)
{
_PrintCfg *prncfg = GrabPrintConfig();
confnet.cd_size = sizeof(CONFNET);
prncfg->confnet = confnet;
return 0;
}
#endif
confnet.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef CONFNET_H
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define CONFNET_H
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
/******************************************************************************
* *
* G L O B A L D E F I N E S *
* *
******************************************************************************/
/*!
* \brief Non-volatile memory location.
*
* Offset into non-volatile memory, where Nut/Net stores the network
* configuration. The default may be overridden by the Configurator.
*/
#ifndef CONFNET_EE_OFFSET
#define CONFNET_EE_OFFSET 64
#endif
#ifndef CONFNET_MAX_IF
#define CONFNET_MAX_IF 1
#endif
/******************************************************************************
* *
* S T R U C T U R E D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Network configuration type.
*/
typedef struct _CONFNET CONFNET;
/*!
* \struct _CONFNET confnet.h sys/confnet.h
* \brief Network configuration structure.
*
* Applications may directly access the global variable \ref confnet to
* read or modify the current network configuration.
*/
#if defined(__ICCARM__)
#pragma diag_suppress = Pa039 // Use of address of unaligned structure member
#pragma pack ( 1 )
#endif
struct _CONFNET {
/*! \brief Size of this structure.
*
* Used by Nut/Net to verify, that the structure contents is valid
* after reading it from non-volatile memory.
*/
u_char cd_size;
/*! \brief Magic cookie.
*
* Contains the device name of the network interface.
*/
char cd_name[9];
/*! \brief Ethernet MAC address.
*
* Unique Ethernet address of the network interface.
*/
u_char cdn_mac[6];
/*! \brief Last used IP address.
*
* Each time Nut/Net receives an IP address during boot, it
* will store the address in here.
*
* If no fixed IP address has been configured (cdn_cip_addr
* contains 0.0.0.0) and if no DHCP server is available, then
* Nut/Net will use this one, if it is not 0.0.0.0.
*/
u_long cdn_ip_addr;
/*! \brief IP netmask.
*
* The netmask is used to determine which machines are
* available in the local network.
*/
u_long cdn_ip_mask;
/*! \brief Default route.
*
* Nut/Net will redirect IP packets to this node, if the
* target IP is not located in the local network.
*/
u_long cdn_gateway;
/*! \brief Configured IP address.
*
* If this address is set to 0.0.0.0, Nut/Net will try
* to obtain one from the DHCP server.
*/
u_long cdn_cip_addr;
/*! \brief Primary DNS IP address.
*/
u_long cdn_pdns;
/*! \brief Secondary DNS IP address.
*/
u_long cdn_sdns;
};
#if defined(__ICCARM__)
#pragma pack ( )
#endif
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - N O I N I T I A L I Z E R S *
* *
******************************************************************************/
#ifdef CONFNET_C
#define EXTERN
#else
#define EXTERN extern
#endif
/*!
* \brief Global network configuration structure.
*
* Contains the current network configuration. Nut/Net will load
* this structure from non-volatile memory during initialization.
*/
EXTERN CONFNET confnet;
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
u_char *NutNetGetMAC(void);
u_short NutNetGetPort(void);
#undef EXTERN
#ifdef __cplusplus
} /* End of extern "C" { */
#endif /* __cplusplus */
#endif
errno.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef ERRNO_H
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ERRNO_H
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
/******************************************************************************
* *
* G L O B A L D E F I N E S *
* *
******************************************************************************/
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* Input/output error */
#define ENXIO 6 /* Device not configured */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file descriptor */
#define ECHILD 10 /* No child processes */
#define EDEADLK 11 /* Resource deadlock avoided */
/* 11 was EAGAIN */
#define ENOMEM 12 /* Cannot allocate memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* Operation not supported by device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* Too many open files in system */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Inappropriate ioctl for device */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
/* math software */
#define EDOM 33 /* Numerical argument out of domain */
#define ERANGE 34 /* Result too large */
/* non-blocking and interrupt i/o */
#define EAGAIN 35 /* Resource temporarily unavailable */
#define EWOULDBLOCK EAGAIN /* Operation would block */
#define EINPROGRESS 36 /* Operation now in progress */
#define EALREADY 37 /* Operation already in progress */
/* ipc/network software -- argument errors */
#define ENOTSOCK 38 /* Socket operation on non-socket */
#define EDESTADDRREQ 39 /* Destination address required */
#define EMSGSIZE 40 /* Message too long */
#define EPROTOTYPE 41 /* Protocol wrong type for socket */
#define ENOPROTOOPT 42 /* Protocol not available */
#define EPROTONOSUPPORT 43 /* Protocol not supported */
#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
#define EOPNOTSUPP 45 /* Operation not supported */
#define EPFNOSUPPORT 46 /* Protocol family not supported */
#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */
#define EADDRINUSE 48 /* Address already in use */
#define EADDRNOTAVAIL 49 /* Can't assign requested address */
/* ipc/network software -- operational errors */
#define ENETDOWN 50 /* Network is down */
#define ENETUNREACH 51 /* Network is unreachable */
#define ENETRESET 52 /* Network dropped connection on reset */
#define ECONNABORTED 53 /* Software caused connection abort */
#define ECONNRESET 54 /* Connection reset by peer */
#define ENOBUFS 55 /* No buffer space available */
#define EISCONN 56 /* Socket is already connected */
#define ENOTCONN 57 /* Socket is not connected */
#define ESHUTDOWN 58 /* Can't send after socket shutdown */
#define ETOOMANYREFS 59 /* Too many references: can't splice */
#define ETIMEDOUT 60 /* Operation timed out */
#define ECONNREFUSED 61 /* Connection refused */
#define ELOOP 62 /* Too many levels of symbolic links */
#define ENAMETOOLONG 63 /* File name too long */
/* should be rearranged */
#define EHOSTDOWN 64 /* Host is down */
#define EHOSTUNREACH 65 /* No route to host */
#define ENOTEMPTY 66 /* Directory not empty */
/******************************************************************************
* *
* S T R U C T U R E D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - N O I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
#ifdef __cplusplus
} /* End of extern "C" { */
#endif /* __cplusplus */
#endif
ether.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef ETHER_H
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ETHER_H
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "netbuf.h"
#include "if_var.h"
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
/******************************************************************************
* *
* G L O B A L D E F I N E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* S T R U C T U R E D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - N O I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
void NutEtherInput(NUTDEVICE *dev, NETBUF *nb);
int NutEtherOutput(NUTDEVICE *dev, u_short type, u_char *ha, NETBUF *nb);
#ifdef __cplusplus
} /* End of extern "C" { */
#endif /* __cplusplus */
#endif
ethin.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ETHIN_C
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "Common.h"
#include "XCore.h"
#include "if_ether.h"
#include "ip.h"
#include "in.h"
#include "ether.h"
#if defined(NUTNET)
/******************************************************************************
* *
* L O C A L D E F I N E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L T Y P E D E F S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L I N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L U N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Handle incoming Ethernet frames.
*
* Splits the Ethernet frame into the data link and the
* network part. Then the frame is routed to the proper
* handler, based on the type field in the Ethernet header.
*
* If the frame neither contains an IP nor an ARP type
* telegram, then it is silently discarded.
*
* \note This routine is called by the device driver on
* incoming ethernet packets. Applications typically do
* not call this function.
*
* \param dev Identifies the device that received the frame.
* \param nb Pointer to a network buffer structure containing
* the ethernet frame.
*/
void NutEtherInput(NUTDEVICE * dev, NETBUF * nb)
{
ETHERHDR *eh;
/*
* Split the Ethernet frame.
*/
eh = (ETHERHDR *) nb->nb_dl.vp;
nb->nb_nw.vp = eh + 1;
nb->nb_nw.sz = nb->nb_dl.sz - sizeof(ETHERHDR);
nb->nb_dl.sz = sizeof(ETHERHDR);
/*
* Route frame to the correct handler.
*/
switch (ntohs(eh->ether_type)) {
case ETHERTYPE_IP:
NutIpInput(dev, nb);
break;
case ETHERTYPE_ARP:
NutArpInput(dev, nb);
break;
default:
NutNetBufFree(nb);
break;
}
}
#endif
ethout.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ETHEROUT_C
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include <string.h>
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "Common.h"
#include "XCore.h"
#include "if_ether.h"
#include "in.h"
#include "ether.h"
#if defined(NUTNET)
/******************************************************************************
* *
* L O C A L D E F I N E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L T Y P E D E F S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L I N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L U N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Send Ethernet frame.
*
* Send an Ethernet frame of a given type using the specified device.
*
* \param dev Identifies the device to use.
* \param type Type of this frame, either ETHERTYPE_IP or ETHERTYPE_ARP.
* \param ha MAC address of the destination, set null for broadcasts.
* \param nb Network buffer structure containing the packet to be sent.
* The structure must have been allocated by a previous
* call NutNetBufAlloc() and will be freed if this function
* returns with an error.
*
* \return 0 on success, -1 in case of any errors.
*/
int NutEtherOutput(NUTDEVICE * dev, u_short type, u_char * ha, NETBUF * nb)
{
ETHERHDR *eh;
IFNET *nif;
if (NutNetBufAlloc(nb, NBAF_DATALINK, sizeof(ETHERHDR)) == 0)
return -1;
eh = (ETHERHDR *) nb->nb_dl.vp;
nif = dev->dev_icb;
memcpy(eh->ether_shost, nif->if_mac, 6);
if (ha)
memcpy(eh->ether_dhost, ha, 6);
else
memset(eh->ether_dhost, 0xff, 6);
eh->ether_type = htons(type);
/*
* Call the network device output routine.
*/
if((*nif->if_send) (dev, nb)) {
NutNetBufFree(nb);
return -1;
}
return 0;
}
#endif
icmp.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef ICMP_H
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ICMP_H
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "netbuf.h"
#include "if_var.h"
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
/******************************************************************************
* *
* G L O B A L D E F I N E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* S T R U C T U R E D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - N O I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
void NutIcmpInput(NUTDEVICE *dev, NETBUF *nb);
int NutIcmpOutput(u_char type, u_long dest, NETBUF *nb);
int NutIcmpReply(u_char type, u_char code, u_long spec, u_long dest, NETBUF *nb);
int NutIcmpResponse(u_char type, u_char code, u_long spec, NETBUF * nb);
#ifdef __cplusplus
} /* End of extern "C" { */
#endif /* __cplusplus */
#endif
icmpin.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ICMPIN_C
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "Common.h"
#include "XCore.h"
#include "ip_icmp.h"
#include "ipcsum.h"
#include "icmp.h"
#include "socket.h"
#include "tcp.h"
#include "udp.h"
#include "in.h"
#include "errno.h"
#if defined(NUTNET)
/******************************************************************************
* *
* L O C A L D E F I N E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L T Y P E D E F S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L I N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Translation table from icmp error code to errno.
*/
static CONST int icmp_code2errno[16] =
{
ENETUNREACH,
EHOSTUNREACH,
ENOPROTOOPT,
ECONNREFUSED,
EMSGSIZE,
EOPNOTSUPP,
ENETUNREACH,
EHOSTDOWN,
ENETUNREACH,
ENETUNREACH,
EHOSTUNREACH,
ENETUNREACH,
EHOSTUNREACH,
EHOSTUNREACH,
EHOSTUNREACH,
EHOSTUNREACH,
};
/******************************************************************************
* *
* L O C A L U N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*
* Send out ICMP echo response.
*/
static int NutIcmpReflect(NUTDEVICE * dev, u_char type, NETBUF * nb)
{
IPHDR *ip;
u_long dest;
IFNET *nif;
ip = nb->nb_nw.vp;
dest = ip->ip_src;
nif = dev->dev_icb;
ip->ip_src = nif->if_local_ip;
ip->ip_ttl = MAXTTL;
return NutIcmpOutput(type, dest, nb);
}
/*
* Process incoming ICMP messages for destination unreachable.
*/
static int NutIcmpUnreach(NETBUF * nb, int icmp_code)
{
IPHDR *ih;
if (nb->nb_ap.sz < sizeof(IPHDR) + 8)
return -1;
ih = nb->nb_ap.vp;
switch (ih->ip_p) {
case IPPROTO_TCP:
{
TCPHDR *th;
TCPSOCKET *sock_tcp;
th = (TCPHDR *) ((char *) ih) + sizeof(IPHDR);
sock_tcp = NutTcpFindSocket(th->th_dport, th->th_sport, ih->ip_src);
if (sock_tcp == 0)
return -1;
if (sock_tcp->so_state != TCPS_SYN_SENT && sock_tcp->so_state != TCPS_ESTABLISHED)
return -1;
NutTcpAbortSocket(sock_tcp, icmp_code2errno[icmp_code]);
}
break;
#ifdef NUT_UDP_ICMP_SUPPORT
case IPPROTO_UDP:
{
UDPHDR *uh;
UDPSOCKET *sock_udp;
uh = (UDPHDR *) (((char *) ih) + sizeof(IPHDR));
sock_udp = NutUdpFindSocket(uh->uh_dport);
if (sock_udp == NULL)
return -1;
if (NutUdpSetSocketError(sock_udp, ih->ip_dst, uh->uh_dport, icmp_code2errno[icmp_code]))
return -1;
}
break;
#endif
default:
return -1;
}
return 0;
}
/*!
* \brief Handle incoming ICMP packets.
*
* Incoming ICMP packets are processed in the background.
* NutNet currently handles echo request and destination
* unreachable packets. Any other packet type is silently
* discarded.
*
* \note This routine is called by the IP layer on incoming
* ICMP datagrams. Applications typically do not call
* this function.
*
* \param dev Identifies the device that received the packet.
* \param nb Pointer to a network buffer structure containing
* the ICMP datagram.
*/
void NutIcmpInput(NUTDEVICE * dev, NETBUF * nb)
{
ICMPHDR *icp = (ICMPHDR *) nb->nb_tp.vp;
/* Silently discard packets, which are too small. */
if (icp == NULL || nb->nb_tp.sz < sizeof(ICMPHDR)) {
NutNetBufFree(nb);
return;
}
nb->nb_ap.sz = nb->nb_tp.sz - sizeof(ICMPHDR);
if (nb->nb_ap.sz) {
nb->nb_ap.vp = icp + 1;
nb->nb_tp.sz = sizeof(ICMPHDR);
}
switch (icp->icmp_type) {
case ICMP_ECHO:
if (NutIcmpReflect(dev, ICMP_ECHOREPLY, nb)) {
break;
}
case ICMP_UNREACH:
NutIcmpUnreach(nb, icp->icmp_code);
default:
NutNetBufFree(nb);
}
}
#endif
icmpout.c 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define ICMPOUT_C
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include <string.h>
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "Common.h"
#include "XCore.h"
#include "in.h"
#include "ip_icmp.h"
#include "ipcsum.h"
#include "icmp.h"
#if defined(NUTNET)
/******************************************************************************
* *
* L O C A L D E F I N E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L T Y P E D E F S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L I N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* L O C A L U N I T I A L I Z E D D A T A D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \brief Send an ICMP datagram.
*
* Known ICMP types are:
*
* - #ICMP_ECHOREPLY Echo reply
* - #ICMP_UNREACH Destination unreachable
* - #ICMP_SOURCEQUENCH Packet lost
* - #ICMP_REDIRECT Shorter route
* - #ICMP_ECHO Echo reply
* - #ICMP_ROUTERADVERT Router advertisement
* - #ICMP_ROUTERSOLICIT Router solicitation
* - #ICMP_TIMXCEED Time exceeded
* - #ICMP_PARAMPROB Bad IP header
* - #ICMP_TSTAMP Timestamp request
* - #ICMP_TSTAMPREPLY Timestamp reply
* - #ICMP_IREQ Information request
* - #ICMP_IREQREPLY Information reply
* - #ICMP_MASKREQ Address mask request
* - #ICMP_MASKREPLY Address mask reply
*
* \param type Type of the ICMP message.
* \param dest Destination IP address.
* \param nb Network buffer structure containing the datagram.
*
* \return 0 on success, -1 otherwise.
*/
int NutIcmpOutput(u_char type, u_long dest, NETBUF * nb)
{
ICMPHDR *icp;
u_short csum;
icp = (ICMPHDR *) nb->nb_tp.vp;
icp->icmp_type = type;
icp->icmp_cksum = 0;
csum = NutIpChkSumPartial(0, nb->nb_tp.vp, nb->nb_tp.sz);
icp->icmp_cksum = NutIpChkSum(csum, nb->nb_ap.vp, nb->nb_ap.sz);
return NutIpOutput(IPPROTO_ICMP, dest, nb);
}
/*!
* \brief Send an ICMP message to a given destination.
*
* \param type Type of the ICMP message. See NutIcmpOutput() for
* a list of valid types.
* \param code Type subcode.
* \param spec Type specific data item.
* \param dest IP address of the target.
* \param nb Network buffer structure containing the message to be sent.
* The structure must have been allocated by a previous
* call NutNetBufAlloc() and will be freed if this function
* returns with an error.
*
* \return 0 on success, -1 otherwise.
*/
int NutIcmpReply(u_char type, u_char code, u_long spec, u_long dest, NETBUF * nb)
{
ICMPHDR *icp;
if ((nb = NutNetBufAlloc(nb, NBAF_TRANSPORT, sizeof(ICMPHDR))) == 0)
return -1;
icp = (ICMPHDR *) nb->nb_tp.vp;
icp->icmp_code = code;
icp->icmp_spec = spec;
return NutIcmpOutput(type, dest, nb);
}
/*!
* \brief Send an ICMP message as a response to a given destination.
*
* \param type Type of the ICMP message. See NutIcmpOutput() for
* a list of valid types.
* \param code Type subcode.
* \param spec Type specific data item.
* \param nb Network buffer structure containing the previously recevied
* network packet. According to RFC792 the complete ip header
* and the first 8 bytes of the transport netbuf is used as the
* application data for the response. If this function returns
* with an error, the buffer is freed. The destination addess is
* taken from the ip header.
*
* \return 0 on success, -1 otherwise.
*/
int NutIcmpResponse(u_char type, u_char code, u_long spec, NETBUF * nb)
{
IPHDR *ip;
u_long dest;
ip = nb->nb_nw.vp;
dest = ip->ip_src;
if ((nb = NutNetBufAlloc(nb, NBAF_APPLICATION, sizeof(IPHDR) + 8)) == 0)
return -1;
memcpy(nb->nb_ap.vp, nb->nb_nw.vp, sizeof(IPHDR));
memcpy((u_char *)nb->nb_ap.vp + sizeof(IPHDR), nb->nb_tp.vp, 8);
return NutIcmpReply(type, code, spec, dest, nb);
}
#endif
if_arp.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef IF_ARP_H
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define IF_ARP_H
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
/******************************************************************************
* *
* G L O B A L D E F I N E S *
* *
******************************************************************************/
#define ARPHRD_ETHER 1 /*!< \brief ethernet hardware format */
#define ARPOP_REQUEST 1 /*!< \brief request to resolve address */
#define ARPOP_REPLY 2 /*!< \brief response to previous request */
/******************************************************************************
* *
* S T R U C T U R E D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \typedef ARPHDR
* \brief ARP packet header type.
*/
#if defined(__ICCARM__)
#pragma diag_suppress = Pa039 // Use of address of unaligned structure member
#pragma pack ( 1 )
#endif
typedef struct arphdr {
u_short ar_hrd; /*!< \brief Format of hardware address.
* Nut/Net supports ARPHRD_ETHER only.
*/
u_short ar_pro; /*!< \brief Format of protocol address.
* Only ETHERTYPE_IP is supported by Nut/Net.
*/
u_char ar_hln; /*!< \brief Length of hardware address. */
u_char ar_pln; /*!< \brief Length of protocol address. */
u_short ar_op; /*!< \brief ARP operation.
* May be either ARPOP_REQUEST or ARPOP_REPLY.
*/
} ARPHDR;
#if defined(__ICCARM__)
#pragma pack ( )
#endif
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - N O I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
#ifdef __cplusplus
} /* End of extern "C" { */
#endif /* __cplusplus */
#endif
if_ether.h 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
#ifndef IF_ETHER_H
/******************************************************************************
* *
* M O D U L E D E F I N E *
* *
******************************************************************************/
#define IF_ETHER_H
/******************************************************************************
* *
* C O M P I L E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* U S E R D E F I N E D I N C L U D E F I L E S *
* *
******************************************************************************/
#include "if_var.h"
#include "if_arp.h"
#ifdef __cplusplus
extern "C" { /* Assume C declarations for C++ */
#endif /* __cplusplus */
/******************************************************************************
* *
* G L O B A L D E F I N E S *
* *
******************************************************************************/
/*! \brief Length of an Ethernet address. */
#define ETHER_ADDR_LEN 6
/*! \brief Length of the Ethernet type field. */
#define ETHER_TYPE_LEN 2
/*! \brief Length of the Ethernet CRC. */
#define ETHER_CRC_LEN 4
/*! \brief Length of an Ethernet header. */
#define ETHER_HDR_LEN (ETHER_ADDR_LEN + ETHER_ADDR_LEN + ETHER_TYPE_LEN)
#ifndef ETHER_MIN_LEN
/*! \brief Minimum frame length, including CRC. */
#define ETHER_MIN_LEN 64
#endif
#ifndef ETHER_MAX_LEN
/*! \brief Maximum frame length, including CRC. */
#define ETHER_MAX_LEN 1518
#endif
/*! \brief Ethernet maximum transfer unit.
*
* Must be checked by the hardware driver.
*/
#define ETHERMTU (ETHER_MAX_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
/*! \brief Ethernet minimum transfer unit.
*
* Must be checked by the hardware driver.
*/
#define ETHERMIN (ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN)
#define ETHERTYPE_IP 0x0800 /*!< \brief IP protocol */
#define ETHERTYPE_ARP 0x0806 /*!< \brief Address resolution protocol */
/*!
* \brief Determine if a given Ethernet address is zero.
*
* \param ea Pointer to a character array containing the address.
*
* Return 1 if the address is zero. Otherwise 0 is returned.
*/
#define ETHER_IS_ZERO(ea) (((ea)[0] | (ea)[1] | (ea)[2] | (ea)[3] | (ea)[4] | (ea)[5]) == 0)
/*!
* \brief Determine if a given Ethernet address is a broadcast address.
*
* \param ea Pointer to a character array containing the address.
*
* Return 1 if the address is a broadcast address. Otherwise 0 is returned.
*/
#define ETHER_IS_BROADCAST(ea) (((ea)[0] & (ea)[1] & (ea)[2] & (ea)[3] & (ea)[4] & (ea)[5]) == 0xFF)
/*!
* \brief Determine if a given Ethernet address is a multicast address.
*
* The broadcast address is defined as a special multicast address.
*
* \param ea Pointer to a character array containing the address.
*
* Return 1 if the address is a multicast address. Otherwise 0 is returned.
*/
#define ETHER_IS_MULTICAST(ea) ((ea)[0] & 1)
/*!
* \brief Determine if a given Ethernet address is a unicast address.
*
* By definition, an address with all zeros is not a valid unicast address.
*
* \param ea Pointer to a character array containing the address.
*
* Return 1 if the address is a unicast address. Otherwise 0 is returned.
*/
#define ETHER_IS_UNICAST(ea) (!ETHER_IS_ZERO(ea) && !ETHER_IS_MULTICAST(ea))
/******************************************************************************
* *
* S T R U C T U R E D E F I N I T I O N S *
* *
******************************************************************************/
/*!
* \typedef ETHERHDR
* \brief Ethernet protocol header type.
*/
#if defined(__ICCARM__)
#pragma diag_suppress = Pa039 // Use of address of unaligned structure member
#pragma pack ( 1 )
#endif
typedef struct ether_header {
/*! \brief Destination MAC address. */
u_char ether_dhost[ETHER_ADDR_LEN];
/*! \brief Source MAC address. */
u_char ether_shost[ETHER_ADDR_LEN];
/*! \brief Protocol type. */
u_short ether_type;
} ETHERHDR;
/*!
* \typedef ETHERARP
* \brief Ethernet ARP protocol type.
*/
#if defined(__ICCARM__)
#pragma diag_suppress = Pa039 // Use of address of unaligned structure member
#pragma pack ( 1 )
#endif
typedef struct ether_arp {
ARPHDR ea_hdr; /*!< \brief Fixed-size header. */
u_char arp_sha[6]; /*!< \brief Source hardware address. */
u_long arp_spa; /*!< \brief Source protocol address. */
u_char arp_tha[6]; /*!< \brief Target hardware address. */
u_long arp_tpa; /*!< \brief Target protocol address. */
} ETHERARP;
#if defined(__ICCARM__)
#pragma pack ( )
#endif
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - N O I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* G L O B A L V A R I A B L E S - I N I T I A L I Z E R S *
* *
******************************************************************************/
/* None */
/******************************************************************************
* *
* F U N C T I O N P R O T O T Y P E S *
* *
******************************************************************************/
u_char *ether_aton(CONST char *str);
char *ether_ntoa(CONST u_char *mac);
void NutArpInput(NUTDEVICE *dev, NETBUF *nb);
NETBUF *NutArpAllocNetBuf(u_short type, u_long ip, u_char *mac);
int NutArpOutput(NUTDEVICE *dev, NETBUF *nb);
void NutArpCacheUpdate(NUTDEVICE *dev, u_long ip, u_char *ha);
int NutArpCacheQuery(NUTDEVICE *dev, u_long ip, u_char *mac);
#ifdef __cplusplus
} /* End of extern "C" { */
#endif /* __cplusplus */
#endif