00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "dispatcher.h"
00032 #include "inet.h"
00033 #include "net/arp.h"
00034 #include "net/net_if.h"
00035 #include "net/ip.h"
00036 #include "net/numbers.h"
00037 #include "net/autoip.h"
00038 #include "os_core.h"
00039
00040
00041 #if (NIP_ARP_ENABLE == 1)
00042
00043 extern nip_net_if_t nip_net_if_list[];
00044 extern nip_disp_state_t nip_disp;
00045
00046
00047 static struct ARP_CACHE arp_cache[ NIP_ARP_CACHE_SIZE ];
00048
00049
00050
00051
00052
00053
00054 #define uint32_gt( i1, i2 ) *i1>*i2
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 static nip_success_t nip_arp_cache_lookup( uint8_t *pr_addr, struct ARP_CACHE **entry )
00069 {
00070 arp_cache_id_t cnt;
00071 nip_success_t res;
00072 struct ARP_CACHE *e;
00073
00074 cnt = 0;
00075 *entry = &arp_cache[ cnt ];
00076 do
00077 {
00078 e = &arp_cache[ cnt ];
00079
00080
00081 if ( uint32_gt( &(*entry)->timestamp, &e->timestamp ) ) *entry = e;
00082
00083 if ( uint32_gt( &e->timestamp, &nip_tickcount() ) )
00084 {
00085 res = NIP_SUCCESS;
00086 }
00087 else if ( pr_addr == NULL )
00088 {
00089 *entry = e;
00090 return NIP_SUCCESS;
00091 }
00092 else
00093 res = NIP_ERROR;
00094
00095
00096
00097 if ( pr_addr != NULL && nip_memcmp( pr_addr, e->pr_addr, NIP_ARP_PR_SIZE ) == 0 )
00098 {
00099 *entry = e;
00100 return res;
00101 }
00102
00103 } while ( ++cnt < NIP_ARP_CACHE_SIZE );
00104
00105
00106 return NIP_ERROR;
00107 }
00108
00109
00110
00111
00112
00113 static void nip_arp_fill_defaults_and_send( nip_net_if_id_t if_id, struct ARP_PACKET *arp )
00114 {
00115 nip_net_if_t *net_if = &nip_net_if_list[ if_id ];
00116 uint8_t *ll_target = arp->tha;
00117
00118 arp->hrd = htons( net_if->phy_conf.type );
00119 arp->pro = NIP_ARP_PR_TYPE;
00120 arp->hln = net_if->phy_conf.hw_addr_size;
00121 arp->pln = NIP_ARP_PR_SIZE;
00122 nip_memcpy( arp->sha, net_if->phy_conf.hw_addr, net_if->phy_conf.hw_addr_size );
00123 nip_memcpy( arp->spa, net_if->ip_conf.addr , NIP_ARP_PR_SIZE );
00124
00125
00126 if ( arp->op[1] == NIP_ARP_OP_REQUEST
00127 #if NIP_AUTOIP_ENABLE == 1
00128
00129
00130 || ( arp->spa[0] == 169 && arp->spa[1] == 254 )
00131 #endif
00132 )
00133 {
00134 ll_target = net_if->phy_conf.hw_brdcst_addr;
00135 }
00136
00137
00138 net_if->phy_conf.hard_send_init(
00139 if_id,
00140 NULL,
00141 NIP_NUM_PR_ARP,
00142 ll_target,
00143 arp->sha,
00144 sizeof( struct ARP_PACKET )
00145 );
00146
00147 net_if->phy_conf.hard_send( if_id, (uint8_t*)arp, sizeof( struct ARP_PACKET ) );
00148 }
00149
00150
00151 static void nip_arp_fill_request( struct ARP_PACKET *arp, uint8_t *tpa )
00152 {
00153 nip_memset ( arp, 0, sizeof( struct ARP_PACKET ) );
00154 arp->op[1] = NIP_ARP_OP_REQUEST;
00155 nip_memcpy( arp->tpa, tpa, NIP_ARP_PR_SIZE );
00156 }
00157
00158
00159
00160
00161 void nip_arp_disp_resolve_any( void )
00162 {
00163 nip_net_trans_id_t id = 0;
00164 nip_net_if_trans_t *trans;
00165 struct ARP_CACHE *cache;
00166
00167 #if NIP_NET_MAX_TRANSMISSIONS > 1
00168 do
00169 {
00170 #endif
00171 trans = &nip_net_trans_list[ id ];
00172 if ( trans->status == NIP_NET_IF_RESOLV_ADDR )
00173 {
00174 if ( trans->time < nip_tickcount()
00175 || NIP_SUCCESS == nip_arp_cache_lookup( trans->params.ip.ll_nw_addr, &cache ) )
00176 {
00177
00178
00179
00180 nip_disp_notify( NIP_DISP_CHECK_TRANS );
00181 nip_disp.next.common.trans = trans;
00182
00183
00184 NIP_CURR_CMD = &nip_ip_disp_send;
00185 return;
00186 }
00187 }
00188 #if NIP_NET_MAX_TRANSMISSIONS > 1
00189 } while ( ++id < NIP_NET_MAX_TRANSMISSIONS );
00190 #endif
00191 }
00192
00193
00194
00195
00196
00197
00198 void nip_arp_disp_resolve( void )
00199 {
00200 struct ARP_CACHE *entry;
00201 struct ARP_PACKET arp;
00202 nip_net_if_trans_t *trans = nip_disp.next.common.trans;
00203
00204
00205 if ( NIP_SUCCESS == nip_arp_cache_lookup( trans->params.ip.ll_nw_addr, &entry ) )
00206 {
00207
00208 nip_memcpy( nip_disp.next.common.remote_hw_addr, entry->hw_addr, NIP_ARP_HW_SIZE );
00209 trans->status = NIP_NET_IF_RTS;
00210 NIP_CURR_CMD = &nip_ip_disp_send;
00211 }
00212 else
00213 {
00214
00215 trans->retrans_cnt++;
00216 trans->time = nip_tickcount() + NIP_ARP_RETRY_INTVL;
00217 if ( trans->retrans_cnt > NIP_ARP_MAX_RETRIES )
00218 {
00219 trans->status = NIP_NET_IF_SEND_HNF;
00220 NIP_CURR_CMD = &nip_ip_disp_send;
00221 }
00222
00223
00224 nip_arp_fill_request( &arp, trans->params.ip.ll_nw_addr );
00225 nip_arp_fill_defaults_and_send( trans->if_id, &arp );
00226 }
00227 }
00228
00229 #if NIP_AUTOIP_ENABLE == 1
00230
00231
00232
00233
00234
00235
00236 void nip_arp_disp_probe_announcement( void )
00237 {
00238 struct ARP_PACKET arp;
00239 #if NIP_NET_IF_COUNT > 1
00240 struct nip_autoip_conf *conf = & NIP_AUTOIP_CONF( NIP_CURR_IF );
00241 #define AUTOIP_CONF_ATTR(attr) conf-> attr
00242 #else
00243 #define AUTOIP_CONF_ATTR(attr) nip_autoip_conf.attr
00244 #endif
00245
00246
00247 nip_arp_fill_request( &arp, AUTOIP_CONF_ATTR(addr));
00248 nip_arp_fill_defaults_and_send( NIP_CURR_IF, &arp );
00249 }
00250
00251 #endif
00252
00253
00254
00255
00256
00257 void nip_disp_arp_receive( void )
00258 {
00259
00260
00261
00262 nip_net_if_id_t if_id = NIP_CURR_IF;
00263 nip_net_if_t *net_if = &nip_net_if_list[ if_id ];
00264 struct ARP_PACKET arp;
00265 struct ARP_CACHE *cache;
00266
00267
00268 if ( sizeof( struct ARP_PACKET ) != net_if->phy_conf.hard_read( if_id, (uint8_t*) &arp, sizeof( struct ARP_PACKET ) ) )
00269 {
00270
00271
00272 return;
00273 }
00274
00275
00276 if ( ntohs(arp.hrd) != net_if->phy_conf.type )
00277 return;
00278
00279
00280 if ( arp.pro != NIP_ARP_PR_TYPE )
00281 return;
00282
00283
00284 if ( arp.hln != net_if->phy_conf.hw_addr_size || arp.pln != NIP_ARP_PR_SIZE )
00285 return;
00286
00287 if ( arp.op[0] == 0x00 )
00288 {
00289 #if NIP_AUTOIP_ENABLE == 1
00290
00291 nip_autoip_arpcheck( if_id, &arp );
00292 #endif
00293
00294
00295 if ( arp.op[1] == NIP_ARP_OP_REQUEST )
00296 {
00297
00298 if ( nip_memcmp( arp.tpa, net_if->ip_conf.addr, 4) == 0 )
00299 {
00300
00301 nip_memcpy( arp.tha, arp.sha, NIP_ARP_PR_SIZE + net_if->phy_conf.hw_addr_size );
00302 arp.op[1] = NIP_ARP_OP_REPLY;
00303
00304 nip_arp_fill_defaults_and_send( NIP_CURR_IF, &arp );
00305 }
00306 }
00307
00308 else if ( arp.op[1] == NIP_ARP_OP_REPLY )
00309 {
00310
00311
00312
00313
00314 nip_arp_cache_lookup( arp.spa, &cache );
00315 nip_memcpy( cache->hw_addr, arp.sha, arp.hln );
00316 nip_memcpy( cache->pr_addr, arp.spa, arp.pln );
00317 cache->timestamp = nip_tickcount() + NIP_ARP_CACHE_LIFE;
00318
00319
00320 NIP_CURR_CMD = &nip_arp_disp_resolve_any;
00321 }
00322 }
00323 }
00324
00325 #endif