| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_arp.c,v 1.184 2015/10/08 08:17:37 roy Exp $ */ | | 1 | /* $NetBSD: if_arp.c,v 1.185 2015/10/13 09:33:35 roy Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 1998, 2000, 2008 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Public Access Networks Corporation ("Panix"). It was developed under | | 8 | * by Public Access Networks Corporation ("Panix"). It was developed under |
9 | * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. | | 9 | * contract to Panix by Eric Haszlakiewicz and Thor Lancelot Simon. |
10 | * | | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | | 11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions | | 12 | * modification, are permitted provided that the following conditions |
13 | * are met: | | 13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
| @@ -58,27 +58,27 @@ | | | @@ -58,27 +58,27 @@ |
58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 58 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
59 | * SUCH DAMAGE. | | 59 | * SUCH DAMAGE. |
60 | * | | 60 | * |
61 | * @(#)if_ether.c 8.2 (Berkeley) 9/26/94 | | 61 | * @(#)if_ether.c 8.2 (Berkeley) 9/26/94 |
62 | */ | | 62 | */ |
63 | | | 63 | |
64 | /* | | 64 | /* |
65 | * Ethernet address resolution protocol. | | 65 | * Ethernet address resolution protocol. |
66 | * TODO: | | 66 | * TODO: |
67 | * add "inuse/lock" bit (or ref. count) along with valid bit | | 67 | * add "inuse/lock" bit (or ref. count) along with valid bit |
68 | */ | | 68 | */ |
69 | | | 69 | |
70 | #include <sys/cdefs.h> | | 70 | #include <sys/cdefs.h> |
71 | __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.184 2015/10/08 08:17:37 roy Exp $"); | | 71 | __KERNEL_RCSID(0, "$NetBSD: if_arp.c,v 1.185 2015/10/13 09:33:35 roy Exp $"); |
72 | | | 72 | |
73 | #ifdef _KERNEL_OPT | | 73 | #ifdef _KERNEL_OPT |
74 | #include "opt_ddb.h" | | 74 | #include "opt_ddb.h" |
75 | #include "opt_inet.h" | | 75 | #include "opt_inet.h" |
76 | #endif | | 76 | #endif |
77 | | | 77 | |
78 | #ifdef INET | | 78 | #ifdef INET |
79 | | | 79 | |
80 | #include "bridge.h" | | 80 | #include "bridge.h" |
81 | | | 81 | |
82 | #include <sys/param.h> | | 82 | #include <sys/param.h> |
83 | #include <sys/systm.h> | | 83 | #include <sys/systm.h> |
84 | #include <sys/callout.h> | | 84 | #include <sys/callout.h> |
| @@ -781,223 +781,215 @@ arprequest(struct ifnet *ifp, | | | @@ -781,223 +781,215 @@ arprequest(struct ifnet *ifp, |
781 | * set one up and broadcast a request for the IP address. | | 781 | * set one up and broadcast a request for the IP address. |
782 | * Hold onto this mbuf and resend it once the address | | 782 | * Hold onto this mbuf and resend it once the address |
783 | * is finally resolved. A return value of 1 indicates | | 783 | * is finally resolved. A return value of 1 indicates |
784 | * that desten has been filled in and the packet should be sent | | 784 | * that desten has been filled in and the packet should be sent |
785 | * normally; a 0 return indicates that the packet has been | | 785 | * normally; a 0 return indicates that the packet has been |
786 | * taken over here, either now or for later transmission. | | 786 | * taken over here, either now or for later transmission. |
787 | */ | | 787 | */ |
788 | int | | 788 | int |
789 | arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m, | | 789 | arpresolve(struct ifnet *ifp, struct rtentry *rt, struct mbuf *m, |
790 | const struct sockaddr *dst, u_char *desten) | | 790 | const struct sockaddr *dst, u_char *desten) |
791 | { | | 791 | { |
792 | struct llentry *la; | | 792 | struct llentry *la; |
793 | const struct sockaddr_dl *sdl; | | 793 | const struct sockaddr_dl *sdl; |
794 | int renew; | | 794 | const char *create_lookup; |
795 | int flags = 0; | | 795 | bool renew; |
796 | int error; | | 796 | int error; |
797 | | | 797 | |
798 | KASSERT(m != NULL); | | 798 | KASSERT(m != NULL); |
799 | | | 799 | |
800 | la = arplookup(ifp, m, &satocsin(dst)->sin_addr, 1, 0, 0, rt); | | 800 | la = arplookup(ifp, m, &satocsin(dst)->sin_addr, 0, 0, 0, rt); |
801 | if (la != NULL) | | 801 | if (la == NULL || la->la_rt == NULL) |
802 | rt = la->la_rt; | | 802 | goto notfound; |
803 | | | 803 | |
804 | if (la == NULL || rt == NULL) { | | 804 | rt = la->la_rt; |
805 | ARP_STATINC(ARP_STAT_ALLOCFAIL); | | | |
806 | log(LOG_DEBUG, | | | |
807 | "arpresolve: can't allocate llinfo on %s for %s\n", | | | |
808 | ifp->if_xname, in_fmtaddr(satocsin(dst)->sin_addr)); | | | |
809 | m_freem(m); | | | |
810 | if (la != NULL) | | | |
811 | LLE_RUNLOCK(la); | | | |
812 | return 0; | | | |
813 | } | | | |
814 | sdl = satocsdl(rt->rt_gateway); | | 805 | sdl = satocsdl(rt->rt_gateway); |
815 | /* | | 806 | /* |
816 | * Check the address family and length is valid, the address | | 807 | * Check the address family and length is valid, the address |
817 | * is resolved; otherwise, try to resolve. | | 808 | * is resolved; otherwise, try to resolve. |
818 | */ | | 809 | */ |
819 | if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) && | | 810 | if ((rt->rt_expire == 0 || rt->rt_expire > time_uptime) && |
820 | sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { | | 811 | sdl->sdl_family == AF_LINK && sdl->sdl_alen != 0) { |
821 | memcpy(desten, CLLADDR(sdl), | | 812 | memcpy(desten, CLLADDR(sdl), |
822 | min(sdl->sdl_alen, ifp->if_addrlen)); | | 813 | min(sdl->sdl_alen, ifp->if_addrlen)); |
823 | rt->rt_pksent = time_uptime; /* Time for last pkt sent */ | | 814 | rt->rt_pksent = time_uptime; /* Time for last pkt sent */ |
824 | LLE_RUNLOCK(la); | | 815 | LLE_RUNLOCK(la); |
825 | return 1; | | 816 | return 1; |
826 | } | | 817 | } |
827 | | | 818 | |
828 | /* | | 819 | /* |
829 | * Re-send the ARP request when appropriate. | | 820 | * Re-send the ARP request when appropriate. |
830 | */ | | 821 | */ |
831 | #ifdef DIAGNOSTIC | | 822 | #ifdef DIAGNOSTIC |
832 | if (rt->rt_expire == 0) { | | 823 | if (rt->rt_expire == 0) { |
833 | /* This should never happen. (Should it? -gwr) */ | | 824 | /* This should never happen. (Should it? -gwr) */ |
834 | printf("arpresolve: unresolved and rt_expire == 0\n"); | | 825 | printf("arpresolve: unresolved and rt_expire == 0\n"); |
835 | /* Set expiration time to now (expired). */ | | 826 | /* Set expiration time to now (expired). */ |
836 | rt->rt_expire = time_uptime; | | 827 | rt->rt_expire = time_uptime; |
837 | } | | 828 | } |
838 | #endif | | 829 | #endif |
839 | | | 830 | |
840 | retry: | | 831 | notfound: |
841 | if (la == NULL) { | | 832 | if (la == NULL) { |
842 | IF_AFDATA_RLOCK(ifp); | | | |
843 | la = lla_lookup(LLTABLE(ifp), flags, dst); | | | |
844 | IF_AFDATA_RUNLOCK(ifp); | | | |
845 | } | | | |
846 | | | | |
847 | #ifdef IFF_STATICARP /* FreeBSD */ | | 833 | #ifdef IFF_STATICARP /* FreeBSD */ |
848 | #define _IFF_NOARP (IFF_NOARP | IFF_STATICARP) | | 834 | #define _IFF_NOARP (IFF_NOARP | IFF_STATICARP) |
849 | #else | | 835 | #else |
850 | #define _IFF_NOARP IFF_NOARP | | 836 | #define _IFF_NOARP IFF_NOARP |
851 | #endif | | 837 | #endif |
852 | if ((la == NULL) && ((flags & LLE_EXCLUSIVE) == 0) | | 838 | if (ifp->if_flags & _IFF_NOARP) { |
853 | && ((ifp->if_flags & _IFF_NOARP) == 0)) | | 839 | m_freem(m); |
854 | { | | 840 | return 0; |
855 | flags |= LLE_EXCLUSIVE; | | 841 | } |
| | | 842 | #undef _IFF_NOARP |
| | | 843 | create_lookup = "create"; |
856 | IF_AFDATA_WLOCK(ifp); | | 844 | IF_AFDATA_WLOCK(ifp); |
857 | la = lla_create(LLTABLE(ifp), flags, dst); | | 845 | la = lla_create(LLTABLE(ifp), LLE_EXCLUSIVE, dst); |
858 | IF_AFDATA_WUNLOCK(ifp); | | 846 | IF_AFDATA_WUNLOCK(ifp); |
859 | | | 847 | if (la == NULL) |
860 | if (la == NULL) { | | 848 | ARP_STATINC(ARP_STAT_ALLOCFAIL); |
861 | log(LOG_DEBUG, | | 849 | } else if (LLE_TRY_UPGRADE(la) == 0) { |
862 | "%s: failed to create llentry for %s on %s\n", | | 850 | create_lookup = "lookup"; |
863 | __func__, inet_ntoa(satocsin(dst)->sin_addr), | | 851 | LLE_RUNLOCK(la); |
864 | ifp->if_xname); | | 852 | IF_AFDATA_RLOCK(ifp); |
865 | } | | 853 | la = lla_lookup(LLTABLE(ifp), LLE_EXCLUSIVE, dst); |
| | | 854 | IF_AFDATA_RUNLOCK(ifp); |
866 | } | | 855 | } |
867 | #undef _IFF_NOARP | | | |
868 | | | 856 | |
869 | if (la == NULL) { | | 857 | if (la == NULL) { |
| | | 858 | log(LOG_DEBUG, |
| | | 859 | "%s: failed to %s llentry for %s on %s\n", |
| | | 860 | __func__, create_lookup, inet_ntoa(satocsin(dst)->sin_addr), |
| | | 861 | ifp->if_xname); |
870 | m_freem(m); | | 862 | m_freem(m); |
871 | return 0; | | 863 | return 0; |
872 | } | | 864 | } |
873 | | | 865 | |
| | | 866 | /* Just in case */ |
| | | 867 | if (la->la_rt == NULL) { |
| | | 868 | log(LOG_DEBUG, |
| | | 869 | "%s: valid llentry has no rtentry for %s on %s\n", |
| | | 870 | __func__, inet_ntoa(satocsin(dst)->sin_addr), |
| | | 871 | ifp->if_xname); |
| | | 872 | m_freem(m); |
| | | 873 | return 0; |
| | | 874 | } |
| | | 875 | rt = la->la_rt; |
| | | 876 | |
874 | if ((la->la_flags & LLE_VALID) && | | 877 | if ((la->la_flags & LLE_VALID) && |
875 | ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) { | | 878 | ((la->la_flags & LLE_STATIC) || la->la_expire > time_uptime)) |
| | | 879 | { |
| | | 880 | sdl = satocsdl(rt->rt_gateway); |
876 | memcpy(desten, CLLADDR(sdl), | | 881 | memcpy(desten, CLLADDR(sdl), |
877 | min(sdl->sdl_alen, ifp->if_addrlen)); | | 882 | min(sdl->sdl_alen, ifp->if_addrlen)); |
878 | renew = 0; | | 883 | renew = false; |
879 | /* | | 884 | /* |
880 | * If entry has an expiry time and it is approaching, | | 885 | * If entry has an expiry time and it is approaching, |
881 | * see if we need to send an ARP request within this | | 886 | * see if we need to send an ARP request within this |
882 | * arpt_down interval. | | 887 | * arpt_down interval. |
883 | */ | | 888 | */ |
884 | if (!(la->la_flags & LLE_STATIC) && | | 889 | if (!(la->la_flags & LLE_STATIC) && |
885 | time_uptime + la->la_preempt > la->la_expire) { | | 890 | time_uptime + la->la_preempt > la->la_expire) |
886 | renew = 1; | | 891 | { |
| | | 892 | renew = true; |
887 | la->la_preempt--; | | 893 | la->la_preempt--; |
888 | } | | 894 | } |
889 | | | 895 | |
890 | if (flags & LLE_EXCLUSIVE) | | 896 | LLE_WUNLOCK(la); |
891 | LLE_WUNLOCK(la); | | | |
892 | else | | | |
893 | LLE_RUNLOCK(la); | | | |
894 | | | 897 | |
895 | if (renew == 1) { | | 898 | if (renew) { |
896 | const u_int8_t *enaddr = | | 899 | const u_int8_t *enaddr = |
897 | #if NCARP > 0 | | 900 | #if NCARP > 0 |
898 | (rt->rt_ifp->if_type == IFT_CARP) ? | | 901 | (rt->rt_ifp->if_type == IFT_CARP) ? |
899 | CLLADDR(rt->rt_ifp->if_sadl): | | 902 | CLLADDR(rt->rt_ifp->if_sadl): |
900 | #endif | | 903 | #endif |
901 | CLLADDR(ifp->if_sadl); | | 904 | CLLADDR(ifp->if_sadl); |
902 | arprequest(ifp, &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, | | 905 | arprequest(ifp, |
| | | 906 | &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, |
903 | &satocsin(dst)->sin_addr, enaddr); | | 907 | &satocsin(dst)->sin_addr, enaddr); |
904 | } | | 908 | } |
905 | | | 909 | |
906 | return 1; | | 910 | return 1; |
907 | } | | 911 | } |
908 | | | 912 | |
909 | if (la->la_flags & LLE_STATIC) { /* should not happen! */ | | 913 | if (la->la_flags & LLE_STATIC) { /* should not happen! */ |
910 | log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n", | | 914 | log(LOG_DEBUG, "arpresolve: ouch, empty static llinfo for %s\n", |
911 | inet_ntoa(satocsin(dst)->sin_addr)); | | 915 | inet_ntoa(satocsin(dst)->sin_addr)); |
912 | m_freem(m); | | 916 | m_freem(m); |
913 | error = EINVAL; | | 917 | error = EINVAL; |
914 | goto done; | | 918 | goto done; |
915 | } | | 919 | } |
916 | | | 920 | |
917 | renew = (la->la_asked == 0 || la->la_expire != time_uptime); | | 921 | renew = (la->la_asked == 0 || la->la_expire != time_uptime); |
918 | if (renew && (flags & LLE_EXCLUSIVE) == 0) { | | | |
919 | flags |= LLE_EXCLUSIVE; | | | |
920 | LLE_RUNLOCK(la); | | | |
921 | la = NULL; | | | |
922 | goto retry; | | | |
923 | } | | | |
924 | | | 922 | |
925 | /* | | 923 | /* |
926 | * There is an arptab entry, but no ethernet address | | 924 | * There is an arptab entry, but no ethernet address |
927 | * response yet. Add the mbuf to the list, dropping | | 925 | * response yet. Add the mbuf to the list, dropping |
928 | * the oldest packet if we have exceeded the system | | 926 | * the oldest packet if we have exceeded the system |
929 | * setting. | | 927 | * setting. |
930 | */ | | 928 | */ |
931 | LLE_WLOCK_ASSERT(la); | | 929 | LLE_WLOCK_ASSERT(la); |
932 | if (la->la_numheld >= arp_maxhold) { | | 930 | if (la->la_numheld >= arp_maxhold) { |
933 | if (la->la_hold != NULL) { | | 931 | if (la->la_hold != NULL) { |
934 | struct mbuf *next = la->la_hold->m_nextpkt; | | 932 | struct mbuf *next = la->la_hold->m_nextpkt; |
935 | m_freem(la->la_hold); | | 933 | m_freem(la->la_hold); |
936 | la->la_hold = next; | | 934 | la->la_hold = next; |
937 | la->la_numheld--; | | 935 | la->la_numheld--; |
938 | ARP_STATINC(ARP_STAT_DFRDROPPED); | | 936 | ARP_STATINC(ARP_STAT_DFRDROPPED); |
939 | } | | 937 | } |
940 | } | | 938 | } |
941 | if (la->la_hold != NULL) { | | 939 | if (la->la_hold != NULL) { |
942 | struct mbuf *curr = la->la_hold; | | 940 | struct mbuf *curr = la->la_hold; |
943 | while (curr->m_nextpkt != NULL) | | 941 | while (curr->m_nextpkt != NULL) |
944 | curr = curr->m_nextpkt; | | 942 | curr = curr->m_nextpkt; |
945 | curr->m_nextpkt = m; | | 943 | curr->m_nextpkt = m; |
946 | } else | | 944 | } else |
947 | la->la_hold = m; | | 945 | la->la_hold = m; |
948 | la->la_numheld++; | | 946 | la->la_numheld++; |
949 | if (renew == 0 && (flags & LLE_EXCLUSIVE)) { | | 947 | if (!renew) |
950 | flags &= ~LLE_EXCLUSIVE; | | | |
951 | LLE_DOWNGRADE(la); | | 948 | LLE_DOWNGRADE(la); |
952 | } | | | |
953 | | | 949 | |
954 | /* | | 950 | /* |
955 | * Return EWOULDBLOCK if we have tried less than arp_maxtries. It | | 951 | * Return EWOULDBLOCK if we have tried less than arp_maxtries. It |
956 | * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH | | 952 | * will be masked by ether_output(). Return EHOSTDOWN/EHOSTUNREACH |
957 | * if we have already sent arp_maxtries ARP requests. Retransmit the | | 953 | * if we have already sent arp_maxtries ARP requests. Retransmit the |
958 | * ARP request, but not faster than one request per second. | | 954 | * ARP request, but not faster than one request per second. |
959 | */ | | 955 | */ |
960 | if (la->la_asked < arp_maxtries) | | 956 | if (la->la_asked < arp_maxtries) |
961 | error = EWOULDBLOCK; /* First request. */ | | 957 | error = EWOULDBLOCK; /* First request. */ |
962 | else | | 958 | else |
963 | error = (rt->rt_flags & RTF_GATEWAY) ? | | 959 | error = (rt->rt_flags & RTF_GATEWAY) ? |
964 | EHOSTUNREACH : EHOSTDOWN; | | 960 | EHOSTUNREACH : EHOSTDOWN; |
965 | | | 961 | |
966 | if (renew) { | | 962 | if (renew) { |
967 | const u_int8_t *enaddr = | | 963 | const u_int8_t *enaddr = |
968 | #if NCARP > 0 | | 964 | #if NCARP > 0 |
969 | (rt->rt_ifp->if_type == IFT_CARP) ? | | 965 | (rt->rt_ifp->if_type == IFT_CARP) ? |
970 | CLLADDR(rt->rt_ifp->if_sadl): | | 966 | CLLADDR(rt->rt_ifp->if_sadl): |
971 | #endif | | 967 | #endif |
972 | CLLADDR(ifp->if_sadl); | | 968 | CLLADDR(ifp->if_sadl); |
973 | LLE_ADDREF(la); | | 969 | LLE_ADDREF(la); |
974 | la->la_expire = time_uptime; | | 970 | la->la_expire = time_uptime; |
975 | callout_reset(&la->la_timer, hz * arpt_down, | | 971 | callout_reset(&la->la_timer, hz * arpt_down, |
976 | arptimer, la); | | 972 | arptimer, la); |
977 | la->la_asked++; | | 973 | la->la_asked++; |
978 | if (flags & LLE_EXCLUSIVE) | | 974 | LLE_WUNLOCK(la); |
979 | LLE_WUNLOCK(la); | | 975 | |
980 | else | | | |
981 | LLE_RUNLOCK(la); | | | |
982 | arprequest(ifp, &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, | | 976 | arprequest(ifp, &satocsin(rt->rt_ifa->ifa_addr)->sin_addr, |
983 | &satocsin(dst)->sin_addr, enaddr); | | 977 | &satocsin(dst)->sin_addr, enaddr); |
984 | return error == 0; | | 978 | return error == 0; |
985 | } | | 979 | } |
986 | done: | | 980 | done: |
987 | if (flags & LLE_EXCLUSIVE) | | 981 | LLE_RUNLOCK(la); |
988 | LLE_WUNLOCK(la); | | 982 | |
989 | else | | | |
990 | LLE_RUNLOCK(la); | | | |
991 | return error == 0; | | 983 | return error == 0; |
992 | } | | 984 | } |
993 | | | 985 | |
994 | /* | | 986 | /* |
995 | * Common length and type checks are done here, | | 987 | * Common length and type checks are done here, |
996 | * then the protocol-specific routine is called. | | 988 | * then the protocol-specific routine is called. |
997 | */ | | 989 | */ |
998 | void | | 990 | void |
999 | arpintr(void) | | 991 | arpintr(void) |
1000 | { | | 992 | { |
1001 | struct mbuf *m; | | 993 | struct mbuf *m; |
1002 | struct arphdr *ar; | | 994 | struct arphdr *ar; |
1003 | int s; | | 995 | int s; |