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
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "lwip/inet.h"
00042 #include "netif/arp.h"
00043 #include "lwip/ip.h"
00044
00045 #if LWIP_DHCP
00046 # include "lwip/dhcp.h"
00047 #endif
00048
00049
00050 #define ARP_MAXAGE 2
00051
00052 #define HWTYPE_ETHERNET 1
00053
00054 #define ARP_REQUEST 1
00055 #define ARP_REPLY 2
00056 #define htons HTONS
00057 #define htonl HTONL
00058
00059
00060 PACK_STRUCT_BEGIN
00061 struct arp_hdr {
00062 PACK_STRUCT_FIELD(struct eth_hdr ethhdr);
00063 PACK_STRUCT_FIELD(u16_t hwtype);
00064 PACK_STRUCT_FIELD(u16_t proto);
00065 PACK_STRUCT_FIELD(u16_t _hwlen_protolen);
00066 PACK_STRUCT_FIELD(u16_t opcode);
00067 PACK_STRUCT_FIELD(struct eth_addr shwaddr);
00068 PACK_STRUCT_FIELD(struct ip_addr sipaddr);
00069 PACK_STRUCT_FIELD(struct eth_addr dhwaddr);
00070 PACK_STRUCT_FIELD(struct ip_addr dipaddr);
00071 } PACK_STRUCT_STRUCT;
00072 PACK_STRUCT_END
00073
00074 #define ARPH_HWLEN(hdr) (NTOHS((hdr)->_hwlen_protolen) >> 8)
00075 #define ARPH_PROTOLEN(hdr) (NTOHS((hdr)->_hwlen_protolen) & 0xff)
00076
00077
00078 #define ARPH_HWLEN_SET(hdr, len) (hdr)->_hwlen_protolen = HTONS(ARPH_PROTOLEN(hdr) | ((len) << 8))
00079 #define ARPH_PROTOLEN_SET(hdr, len) (hdr)->_hwlen_protolen = HTONS((len) | (ARPH_HWLEN(hdr) << 8))
00080
00081 PACK_STRUCT_BEGIN
00082 struct ethip_hdr {
00083 PACK_STRUCT_FIELD(struct eth_hdr eth);
00084 PACK_STRUCT_FIELD(struct ip_hdr ip);
00085 };
00086 PACK_STRUCT_END
00087
00088 struct arp_entry {
00089 struct ip_addr ipaddr;
00090 struct eth_addr ethaddr;
00091 u8_t ctime;
00092 };
00093
00094 static struct arp_entry arp_table[ARP_TABLE_SIZE];
00095 static u8_t ctime;
00096
00097
00098 u8_t get_u8_t_from_char(char c,int low){
00099
00100 if(low){
00101
00102 if((c >= 97) && (c <= 122)) return (c-87);
00103
00104 else if((c >= 65) && (c <= 90)) return (c-55);
00105
00106 else if((c >= 48) && (c <= 57)) return (c-48);
00107 }else{
00108
00109 if((c >= 97) && (c <= 122)) return ((c-87)<<4);
00110
00111 else if((c >= 65) && (c <= 90)) return ((c-55)<<4);
00112
00113 else if((c >= 48) && (c <= 57)) return ((c-48)<<4);
00114 }
00115 return -1;
00116 }
00117
00118
00119 unsigned char get_char_from_u8_t(u8_t value){
00120 if(value < 10){
00121 return (unsigned char)(value + 48);
00122 }else{
00123 return (unsigned char)(value + 55);
00124 }
00125 }
00126
00127
00128 void string2mac(struct eth_addr *mac, char *name){
00129 int i,hop=0;
00130
00131 for(i=0; i<6; i++){
00132 mac->addr[i] = get_u8_t_from_char(name[hop],0) + get_u8_t_from_char(name[hop+1],1);
00133 hop+=3;
00134 }
00135 }
00136
00137
00138 void mac2string(struct eth_addr *mac, char *name){
00139 int i,hop=0;
00140 u8_t aux;
00141
00142 for(i=0; i<5; i++){
00143 aux = mac->addr[i];
00144 name[hop] = get_char_from_u8_t((aux & 0xf0)>>4);
00145 name[hop+1] = get_char_from_u8_t((aux & 0x0f));
00146 name[hop+2] = 0x3a;
00147 hop+=3;
00148 }
00149 name[hop] = get_char_from_u8_t((mac->addr[5] & 0xf0)>>4);
00150 name[hop+1] = get_char_from_u8_t((mac->addr[5] & 0x0f));
00151 }
00152
00153
00154 void
00155 arp_init(void)
00156 {
00157 u8_t i;
00158
00159 for(i = 0; i < ARP_TABLE_SIZE; ++i) {
00160 ip_addr_set(&(arp_table[i].ipaddr),
00161 IP_ADDR_ANY);
00162 }
00163 }
00164
00165 void
00166 arp_tmr(void)
00167 {
00168 u8_t i;
00169
00170 ++ctime;
00171 for(i = 0; i < ARP_TABLE_SIZE; ++i) {
00172 if(!ip_addr_isany(&arp_table[i].ipaddr) &&
00173 ctime - arp_table[i].ctime >= ARP_MAXAGE) {
00174 ip_addr_set(&(arp_table[i].ipaddr),
00175 IP_ADDR_ANY);
00176 }
00177 }
00178 }
00179
00180 static void
00181 add_arp_entry(struct ip_addr *ipaddr, struct eth_addr *ethaddr)
00182 {
00183 u8_t i, j, k;
00184 u8_t maxtime;
00185
00186
00187
00188
00189 for(i = 0; i < ARP_TABLE_SIZE; ++i) {
00190
00191
00192 if(!ip_addr_isany(&arp_table[i].ipaddr)) {
00193
00194
00195 if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
00196
00197 for(k = 0; k < 6; ++k) {
00198 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
00199 }
00200 arp_table[i].ctime = ctime;
00201 return;
00202 }
00203 }
00204 }
00205
00206
00207
00208
00209
00210 for(i = 0; i < ARP_TABLE_SIZE; ++i) {
00211 if(ip_addr_isany(&arp_table[i].ipaddr)) {
00212 break;
00213 }
00214 }
00215
00216
00217
00218 if(i == ARP_TABLE_SIZE) {
00219 maxtime = 0;
00220 j = 0;
00221 for(i = 0; i < ARP_TABLE_SIZE; ++i) {
00222 if(ctime - arp_table[i].ctime > maxtime) {
00223 maxtime = ctime - arp_table[i].ctime;
00224 j = i;
00225 }
00226 }
00227 i = j;
00228 }
00229
00230
00231
00232 ip_addr_set(&arp_table[i].ipaddr, ipaddr);
00233 for(k = 0; k < 6; ++k) {
00234 arp_table[i].ethaddr.addr[k] = ethaddr->addr[k];
00235 }
00236 arp_table[i].ctime = ctime;
00237 return;
00238
00239 }
00240
00241 void
00242 arp_ip_input(struct netif *netif, struct pbuf *p)
00243 {
00244 struct ethip_hdr *hdr;
00245
00246 hdr = p->payload;
00247
00248
00249
00250 if(!ip_addr_maskcmp(&(hdr->ip.src), &(netif->ip_addr), &(netif->netmask))) {
00251 return;
00252 }
00253 add_arp_entry(&(hdr->ip.src), &(hdr->eth.src));
00254 }
00255
00256 struct pbuf *
00257 arp_arp_input(struct netif *netif, struct eth_addr *ethaddr, struct pbuf *p)
00258 {
00259 struct arp_hdr *hdr;
00260 u8_t i;
00261
00262 if(p->tot_len < sizeof(struct arp_hdr)) {
00263
00264 pbuf_free(p);
00265 return NULL;
00266 }
00267
00268 hdr = p->payload;
00269
00270 switch(htons(hdr->opcode)) {
00271 case ARP_REQUEST:
00272
00273
00274
00275 if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
00276 hdr->opcode = htons(ARP_REPLY);
00277
00278 ip_addr_set(&(hdr->dipaddr), &(hdr->sipaddr));
00279 ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
00280
00281 for(i = 0; i < 6; ++i) {
00282 hdr->dhwaddr.addr[i] = hdr->shwaddr.addr[i];
00283 hdr->shwaddr.addr[i] = ethaddr->addr[i];
00284 hdr->ethhdr.dest.addr[i] = hdr->dhwaddr.addr[i];
00285 hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
00286 }
00287
00288 hdr->hwtype = htons(HWTYPE_ETHERNET);
00289 ARPH_HWLEN_SET(hdr, 6);
00290
00291 hdr->proto = htons(ETHTYPE_IP);
00292 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
00293
00294 hdr->ethhdr.type = htons(ETHTYPE_ARP);
00295 return p;
00296 }
00297 break;
00298 case ARP_REPLY:
00299
00300
00301 if(ip_addr_cmp(&(hdr->dipaddr), &(netif->ip_addr))) {
00302 add_arp_entry(&(hdr->sipaddr), &(hdr->shwaddr));
00303 #if (LWIP_DHCP && DHCP_DOES_ARP_CHECK)
00304 dhcp_arp_reply(&hdr->sipaddr);
00305 #endif
00306 }
00307 break;
00308 default:
00309
00310 break;
00311 }
00312
00313 pbuf_free(p);
00314 return NULL;
00315 }
00316
00317 struct eth_addr *
00318 arp_lookup(struct ip_addr *ipaddr)
00319 {
00320 u8_t i;
00321
00322 for(i = 0; i < ARP_TABLE_SIZE; ++i) {
00323 if(ip_addr_cmp(ipaddr, &arp_table[i].ipaddr)) {
00324 return &arp_table[i].ethaddr;
00325 }
00326 }
00327 return NULL;
00328 }
00329
00330 struct pbuf *
00331 arp_query(struct netif *netif, struct eth_addr *ethaddr, struct ip_addr *ipaddr)
00332 {
00333 struct arp_hdr *hdr;
00334 struct pbuf *p;
00335 u8_t i;
00336
00337 p = pbuf_alloc(PBUF_LINK, sizeof(struct arp_hdr), PBUF_RAM);
00338 if(p == NULL) {
00339 return NULL;
00340 }
00341
00342 hdr = p->payload;
00343
00344 hdr->opcode = htons(ARP_REQUEST);
00345
00346 for(i = 0; i < 6; ++i) {
00347 hdr->dhwaddr.addr[i] = 0x00;
00348 hdr->shwaddr.addr[i] = ethaddr->addr[i];
00349 }
00350
00351 ip_addr_set(&(hdr->dipaddr), ipaddr);
00352 ip_addr_set(&(hdr->sipaddr), &(netif->ip_addr));
00353
00354 hdr->hwtype = htons(HWTYPE_ETHERNET);
00355 ARPH_HWLEN_SET(hdr, 6);
00356
00357 hdr->proto = htons(ETHTYPE_IP);
00358 ARPH_PROTOLEN_SET(hdr, sizeof(struct ip_addr));
00359
00360 for(i = 0; i < 6; ++i) {
00361 hdr->ethhdr.dest.addr[i] = 0xff;
00362 hdr->ethhdr.src.addr[i] = ethaddr->addr[i];
00363 }
00364
00365 hdr->ethhdr.type = htons(ETHTYPE_ARP);
00366 return p;
00367 }
00368
00369
00370
00371
00372