* Delete an arp entry */
| 496 | * Delete an arp entry |
| 497 | */ |
| 498 | static int |
| 499 | delete(char *host) |
| 500 | { |
| 501 | struct sockaddr_in *addr, *dst; |
| 502 | struct rt_msghdr *rtm; |
| 503 | struct sockaddr_dl *sdl; |
| 504 | |
| 505 | dst = getaddr(host); |
| 506 | if (dst == NULL) |
| 507 | return (1); |
| 508 | |
| 509 | /* |
| 510 | * Perform a regular entry delete first. |
| 511 | */ |
| 512 | flags &= ~RTF_ANNOUNCE; |
| 513 | |
| 514 | for (;;) { /* try twice */ |
| 515 | rtm = rtmsg(RTM_GET, dst, NULL); |
| 516 | if (rtm == NULL) { |
| 517 | xo_warn("%s", host); |
| 518 | return (1); |
| 519 | } |
| 520 | addr = (struct sockaddr_in *)(rtm + 1); |
| 521 | sdl = (struct sockaddr_dl *)(SA_SIZE(addr) + (char *)addr); |
| 522 | |
| 523 | /* |
| 524 | * With the new L2/L3 restructure, the route |
| 525 | * returned is a prefix route. The important |
| 526 | * piece of information from the previous |
| 527 | * RTM_GET is the interface index. In the |
| 528 | * case of ECMP, the kernel will traverse |
| 529 | * the route group for the given entry. |
| 530 | */ |
| 531 | if (sdl->sdl_family == AF_LINK && |
| 532 | !(rtm->rtm_flags & RTF_GATEWAY) && |
| 533 | valid_type(sdl->sdl_type) ) { |
| 534 | addr->sin_addr.s_addr = dst->sin_addr.s_addr; |
| 535 | break; |
| 536 | } |
| 537 | |
| 538 | /* |
| 539 | * Regular entry delete failed, now check if there |
| 540 | * is a proxy-arp entry to remove. |
| 541 | */ |
| 542 | if (flags & RTF_ANNOUNCE) { |
| 543 | xo_warnx("delete: cannot locate %s", host); |
| 544 | return (1); |
| 545 | } |
| 546 | |
| 547 | flags |= RTF_ANNOUNCE; |
| 548 | } |
| 549 | rtm->rtm_flags |= RTF_LLDATA; |
| 550 | if (rtmsg(RTM_DELETE, dst, NULL) != NULL) { |
| 551 | printf("%s (%s) deleted\n", host, inet_ntoa(addr->sin_addr)); |
| 552 | return (0); |
| 553 | } |
| 554 | return (1); |
| 555 | } |