Changeset 331 for EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/if_ether.c
- Timestamp:
- Jan 21, 2018, 12:10:09 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/asp3_dcre/tinet/netinet/if_ether.c
r321 r331 2 2 * TINET (TCP/IP Protocol Stack) 3 3 * 4 * Copyright (C) 2001-20 09by Dep. of Computer Science and Engineering4 * Copyright (C) 2001-2017 by Dep. of Computer Science and Engineering 5 5 * Tomakomai National College of Technology, JAPAN 6 6 * … … 94 94 #include <net/if_arp.h> 95 95 #include <net/net.h> 96 #include <net/net_endian.h> 96 97 #include <net/net_buf.h> 97 98 #include <net/net_var.h> … … 106 107 #include <net/if_var.h> 107 108 108 #if defined( SUPPORT_INET4) && defined(SUPPORT_ETHER)109 #if defined(_IP4_CFG) && defined(SUPPORT_ETHER) 109 110 110 111 /* … … 118 119 */ 119 120 120 static T_ARP_ENTRY *arp_lookup (T_IN4_ADDR addr, bool_t create);121 121 static void in_arpinput (T_IF_ADDR *ifaddr, T_NET_BUF *input); 122 122 static void arp_timer (void *ignore); 123 123 124 124 /* 125 * in_arpinput -- TCP/IP 用 ARP の入力関数 126 */ 127 128 static void 129 in_arpinput (T_IF_ADDR *ifaddr, T_NET_BUF *input) 130 { 131 T_NET_BUF *pending; 132 T_ETHER_HDR *eth; 133 T_ARP_HDR *arph; 134 T_ETHER_ARP_HDR *et_arph; 135 T_ARP_ENTRY *ent; 136 T_IFNET *ifp = IF_GET_IFNET(); 137 T_IN4_ADDR saddr, taddr; 138 139 et_arph = GET_ETHER_ARP_HDR(input); 140 141 ntoahl(saddr, et_arph->sproto); /* 送信元 IP アドレス */ 142 ntoahl(taddr, et_arph->tproto); /* 解決対象 IP アドレス */ 143 144 /* 145 * 以下の場合はエラー 146 * ・送信ホストの物理アドレスが自分 147 * ・送信ホストの物理アドレスがブロードキャスト 148 */ 149 if (memcmp(et_arph->shost, ifaddr->lladdr, ETHER_ADDR_LEN) == 0 || 150 memcmp(et_arph->shost, ether_broad_cast_addr, ETHER_ADDR_LEN) == 0) 151 goto err_ret; 152 153 /* 154 * 送信ホストの IP アドレスが自分の場合は、重複しているので 155 * 相手にも知らせる。 156 * ただし、自分と相手のアドレスが未定義(IPV4_ADDRANY)の時は何もしない。 157 */ 158 if ((saddr == ifp->in4_ifaddr.addr) && (saddr != IPV4_ADDRANY)) { 159 160 #ifdef ARP_CFG_CALLBACK_DUPLICATED 161 162 if (arp_callback_duplicated(et_arph->shost)) { 163 syslog(LOG_ERROR, "[ARP] IP address duplicated: %s", 164 ip2str(NULL, &ifp->in4_ifaddr.addr), 165 mac2str(NULL, et_arph->shost)); 166 taddr = saddr; 167 goto reply; 168 } 169 else 170 goto buf_rel; 171 172 #else /* of #ifdef ARP_CFG_CALLBACK_DUPLICATED */ 173 174 syslog(LOG_ERROR, "[ARP] IP address duplicated: %s", 175 ip2str(NULL, &ifp->in4_ifaddr.addr), 176 mac2str(NULL, et_arph->shost)); 177 taddr = saddr; 178 goto reply; 179 180 #endif /* of #ifdef ARP_CFG_CALLBACK_DUPLICATED */ 181 182 } 183 184 /* 185 * 以下の場合は何もしない。 186 * ・解決対象 IP アドレスが自分ではない、注: 元の FreeBSD の 187 * 実装では、ARP PROXY 等のため、自分以外の IP アドレスの 188 * 解決も行っているが、本実装では、自分以外の IP 189 * アドレスの解決は行わない。 190 */ 191 if (taddr != ifp->in4_ifaddr.addr) 192 goto buf_rel; 193 194 /* 195 * 送信元 IP アドレスが ARP キャッシュにあるか調べる。 196 * キャッシュになければ、新たにエントリを登録する。 197 */ 198 syscall(wai_sem(SEM_ARP_CACHE_LOCK)); 199 ent = arp_lookup(saddr, true); 200 201 memcpy(ent->mac_addr, et_arph->shost, ETHER_ADDR_LEN); 202 ent->expire = ARP_CACHE_KEEP; 203 204 /* 205 * 送信がペンデングされているフレームがあれば送信する。 206 */ 207 if (ent->hold) { 208 209 /* フレームの Ethernet ヘッダを設定する。*/ 210 memcpy(GET_ETHER_HDR(ent->hold)->dhost, ent->mac_addr, ETHER_ADDR_LEN); 211 212 pending = ent->hold; 213 ent->hold = NULL; 214 syscall(sig_sem(SEM_ARP_CACHE_LOCK)); 215 216 /* ペンディングされているフレームを送信する。*/ 217 IF_RAW_OUTPUT(pending, TMO_FEVR); 218 219 } 220 else 221 syscall(sig_sem(SEM_ARP_CACHE_LOCK)); 222 223 reply: 224 225 arph = GET_ARP_HDR(input); 226 227 /* アドレス解決要求でなければ終了 */ 228 if (ntohs(arph->opcode) != ARPOP_REQUEST) 229 goto buf_rel; 230 231 /* Ethernet ARP ヘッダを設定する。*/ 232 memcpy(et_arph->thost, et_arph->shost, ETHER_ADDR_LEN); 233 memcpy(et_arph->shost, ifaddr->lladdr, ETHER_ADDR_LEN); 234 memcpy(et_arph->tproto, (uint8_t*)&et_arph->sproto, sizeof(T_IN_ADDR)); 235 ahtonl(et_arph->sproto, taddr); 236 237 /* Ethernet ARP ヘッダを設定する。*/ 238 arph->opcode = htons(ARPOP_REPLY); 239 240 /* Ethernet ヘッダを設定する。*/ 241 eth = GET_ETHER_HDR(input); 242 memcpy(eth->dhost, eth->shost, ETHER_ADDR_LEN); 243 memcpy(eth->shost, ifaddr->lladdr, ETHER_ADDR_LEN); 244 245 /* ARP 応答を送信する。*/ 246 IF_RAW_OUTPUT(input, TMO_FEVR); 247 return; 248 249 err_ret: 250 NET_COUNT_ARP(net_count_arp.in_err_packets, 1); 251 buf_rel: 252 syscall(rel_net_buf(input)); 253 } 254 255 /* 256 * arp_timer -- ARP キャッシュの更新 257 */ 258 259 static void 260 arp_timer (void *ignore) 261 { 262 int_t ix; 263 264 syscall(wai_sem(SEM_ARP_CACHE_LOCK)); 265 266 for (ix = NUM_ARP_ENTRY; ix -- > 0; ) { 267 if (arp_cache[ix].expire) { 268 arp_cache[ix].expire -= ARP_TIMER_TMO; 269 if (arp_cache[ix].expire == 0) { 270 /* 送信がペンデングされているフレームがあれば捨てる。*/ 271 if (arp_cache[ix].hold) { 272 NET_COUNT_IP4(net_count_ip4[NC_IP4_OUT_ERR_PACKETS], 1); 273 syscall(rel_net_buf(arp_cache[ix].hold)); 274 } 275 memset(&arp_cache[ix], 0, sizeof(T_ARP_ENTRY)); 276 } 277 } 278 } 279 280 syscall(sig_sem(SEM_ARP_CACHE_LOCK)); 281 timeout(arp_timer, NULL, ARP_TIMER_TMO); 282 } 283 284 /* 125 285 * arp_lookup -- ARP キャッシュの探索と登録 126 286 * … … 128 288 */ 129 289 130 staticT_ARP_ENTRY *290 T_ARP_ENTRY * 131 291 arp_lookup (T_IN4_ADDR addr, bool_t create) 132 292 { … … 170 330 171 331 /* 172 * in_arpinput -- TCP/IP 用 ARP の入力関数173 */174 175 static void176 in_arpinput (T_IF_ADDR *ifaddr, T_NET_BUF *input)177 {178 T_NET_BUF *pending;179 T_ETHER_HDR *eth;180 T_ARP_HDR *arph;181 T_ETHER_ARP_HDR *et_arph;182 T_ARP_ENTRY *ent;183 T_IFNET *ifp = IF_GET_IFNET();184 T_IN4_ADDR saddr, taddr;185 186 et_arph = GET_ETHER_ARP_HDR(input);187 188 ntoahl(saddr, et_arph->sproto); /* 送信元 IP アドレス */189 ntoahl(taddr, et_arph->tproto); /* 解決対象 IP アドレス */190 191 /*192 * 以下の場合はエラー193 * ・送信ホストの物理アドレスが自分194 * ・送信ホストの物理アドレスがブロードキャスト195 */196 if (memcmp(et_arph->shost, ifaddr->lladdr, ETHER_ADDR_LEN) == 0 ||197 memcmp(et_arph->shost, ether_broad_cast_addr, ETHER_ADDR_LEN) == 0)198 goto err_ret;199 200 /*201 * 送信ホストの IP アドレスが自分の場合は、重複しているので202 * 相手にも知らせる。203 */204 if (saddr == ifp->in_ifaddr.addr) {205 206 #ifdef ARP_CFG_CALLBACK_DUPLICATED207 208 if (arp_callback_duplicated(et_arph->shost)) {209 syslog(LOG_ERROR, "[ARP] IP address duplicated: %s", mac2str(NULL, et_arph->shost));210 taddr = saddr;211 goto reply;212 }213 else214 goto buf_rel;215 216 #else /* of #ifdef ARP_CFG_CALLBACK_DUPLICATED */217 218 syslog(LOG_ERROR, "[ARP] IP address duplicated: %s", mac2str(NULL, et_arph->shost));219 taddr = saddr;220 goto reply;221 222 #endif /* of #ifdef ARP_CFG_CALLBACK_DUPLICATED */223 224 }225 226 /*227 * 以下の場合は何もしない。228 * ・解決対象 IP アドレスが自分ではない、注: 元の FreeBSD の229 * 実装では、ARP PROXY 等のため、自分以外の IP アドレスの230 * 解決も行っているが、本実装では、自分以外の IP231 * アドレスの解決は行わない。232 */233 if (taddr != ifp->in_ifaddr.addr)234 goto buf_rel;235 236 /*237 * 送信元 IP アドレスが ARP キャッシュにあるか調べる。238 * キャッシュになければ、新たにエントリを登録する。239 */240 syscall(wai_sem(SEM_ARP_CACHE_LOCK));241 ent = arp_lookup(saddr, true);242 243 memcpy(ent->mac_addr, et_arph->shost, ETHER_ADDR_LEN);244 ent->expire = ARP_CACHE_KEEP;245 246 /*247 * 送信がペンデングされているフレームがあれば送信する。248 */249 if (ent->hold) {250 251 /* フレームの Ethernet ヘッダを設定する。*/252 memcpy(GET_ETHER_HDR(ent->hold)->dhost, ent->mac_addr, ETHER_ADDR_LEN);253 254 pending = ent->hold;255 ent->hold = NULL;256 syscall(sig_sem(SEM_ARP_CACHE_LOCK));257 258 /* ペンディングされているフレームを送信する。*/259 IF_RAW_OUTPUT(pending, TMO_FEVR);260 261 }262 else263 syscall(sig_sem(SEM_ARP_CACHE_LOCK));264 265 reply:266 267 arph = GET_ARP_HDR(input);268 269 /* アドレス解決要求でなければ終了 */270 if (ntohs(arph->opcode) != ARPOP_REQUEST)271 goto buf_rel;272 273 /* Ethernet ARP ヘッダを設定する。*/274 memcpy(et_arph->thost, et_arph->shost, ETHER_ADDR_LEN);275 memcpy(et_arph->shost, ifaddr->lladdr, ETHER_ADDR_LEN);276 memcpy(et_arph->tproto, (uint8_t*)&et_arph->sproto, sizeof(T_IN_ADDR));277 ahtonl(et_arph->sproto, taddr);278 279 /* Ethernet ARP ヘッダを設定する。*/280 arph->opcode = htons(ARPOP_REPLY);281 282 /* Ethernet ヘッダを設定する。*/283 eth = GET_ETHER_HDR(input);284 memcpy(eth->dhost, eth->shost, ETHER_ADDR_LEN);285 memcpy(eth->shost, ifaddr->lladdr, ETHER_ADDR_LEN);286 287 /* ARP 応答を送信する。*/288 IF_RAW_OUTPUT(input, TMO_FEVR);289 return;290 291 err_ret:292 NET_COUNT_ARP(net_count_arp.in_err_packets, 1);293 buf_rel:294 syscall(rel_net_buf(input));295 }296 297 /*298 * arp_timer -- ARP キャッシュの更新299 */300 301 static void302 arp_timer (void *ignore)303 {304 int_t ix;305 306 syscall(wai_sem(SEM_ARP_CACHE_LOCK));307 308 for (ix = NUM_ARP_ENTRY; ix -- > 0; ) {309 if (arp_cache[ix].expire) {310 arp_cache[ix].expire -= ARP_TIMER_TMO;311 if (arp_cache[ix].expire == 0) {312 /* 送信がペンデングされているフレームがあれば捨てる。*/313 if (arp_cache[ix].hold) {314 NET_COUNT_IP4(net_count_ip4[NC_IP4_OUT_ERR_PACKETS], 1);315 syscall(rel_net_buf(arp_cache[ix].hold));316 }317 memset(&arp_cache[ix], 0, sizeof(T_ARP_ENTRY));318 }319 }320 }321 322 syscall(sig_sem(SEM_ARP_CACHE_LOCK));323 timeout(arp_timer, NULL, ARP_TIMER_TMO);324 }325 326 /*327 332 * arp_request -- MAC アドレス解決要求 328 333 */ … … 359 364 /* イーサネット ARP ヘッダを設定する。*/ 360 365 et_arph = GET_ETHER_ARP_HDR(arp_req); 361 src = IF_GET_IFNET()->in _ifaddr.addr;366 src = IF_GET_IFNET()->in4_ifaddr.addr; 362 367 memcpy(et_arph->shost, ifaddr->lladdr, ETHER_ADDR_LEN); 363 368 memset(et_arph->thost, 0, ETHER_ADDR_LEN); … … 444 449 */ 445 450 if (gw == IPV4_ADDR_BROADCAST || 446 gw == ((ifp->in _ifaddr.addr & ifp->in_ifaddr.mask) | ~ifp->in_ifaddr.mask)) {451 gw == ((ifp->in4_ifaddr.addr & ifp->in4_ifaddr.mask) | ~ifp->in4_ifaddr.mask)) { 447 452 memcpy(eth->dhost, ether_broad_cast_addr, ETHER_ADDR_LEN); 448 453 return true; … … 504 509 eaddr->lladdr[1] = UINT_C(0x00); 505 510 eaddr->lladdr[2] = UINT_C(0x5E); 506 eaddr->lladdr[3] = ( maddr & 0x7F0000) >> 16;507 eaddr->lladdr[4] = ( maddr & 0xFF00) >> 8;508 eaddr->lladdr[5] = maddr & 0xFF;511 eaddr->lladdr[3] = (uint8_t)((maddr & 0x7F0000) >> 16); 512 eaddr->lladdr[4] = (uint8_t)((maddr & 0xFF00) >> 8); 513 eaddr->lladdr[5] = (uint8_t)(maddr & 0xFF); 509 514 } 510 515 #endif /* ETHER_CFG_MULTICAST */ 511 516 512 #endif /* of #if defined( SUPPORT_INET4) && defined(SUPPORT_ETHER) */517 #endif /* of #if defined(_IP4_CFG) && defined(SUPPORT_ETHER) */
Note:
See TracChangeset
for help on using the changeset viewer.