in6.c (164033) | in6.c (165118) |
---|---|
1/* $FreeBSD: head/sys/netinet6/in6.c 164033 2006-11-06 13:42:10Z rwatson $ */ | 1/* $FreeBSD: head/sys/netinet6/in6.c 165118 2006-12-12 12:17:58Z bz $ */ |
2/* $KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $ */ 3 4/*- 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions --- 125 unchanged lines hidden (view full) --- 135 * This routine does actual work. 136 */ 137static void 138in6_ifloop_request(int cmd, struct ifaddr *ifa) 139{ 140 struct sockaddr_in6 all1_sa; 141 struct rtentry *nrt = NULL; 142 int e; | 2/* $KAME: in6.c,v 1.259 2002/01/21 11:37:50 keiichi Exp $ */ 3 4/*- 5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions --- 125 unchanged lines hidden (view full) --- 135 * This routine does actual work. 136 */ 137static void 138in6_ifloop_request(int cmd, struct ifaddr *ifa) 139{ 140 struct sockaddr_in6 all1_sa; 141 struct rtentry *nrt = NULL; 142 int e; |
143 char ip6buf[INET6_ADDRSTRLEN]; |
|
143 144 bzero(&all1_sa, sizeof(all1_sa)); 145 all1_sa.sin6_family = AF_INET6; 146 all1_sa.sin6_len = sizeof(struct sockaddr_in6); 147 all1_sa.sin6_addr = in6mask128; 148 149 /* 150 * We specify the address itself as the gateway, and set the 151 * RTF_LLINFO flag, so that the corresponding host route would have 152 * the flag, and thus applications that assume traditional behavior 153 * would be happy. Note that we assume the caller of the function 154 * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest, 155 * which changes the outgoing interface to the loopback interface. 156 */ 157 e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr, 158 (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt); 159 if (e != 0) { 160 /* XXX need more descriptive message */ | 144 145 bzero(&all1_sa, sizeof(all1_sa)); 146 all1_sa.sin6_family = AF_INET6; 147 all1_sa.sin6_len = sizeof(struct sockaddr_in6); 148 all1_sa.sin6_addr = in6mask128; 149 150 /* 151 * We specify the address itself as the gateway, and set the 152 * RTF_LLINFO flag, so that the corresponding host route would have 153 * the flag, and thus applications that assume traditional behavior 154 * would be happy. Note that we assume the caller of the function 155 * (probably implicitly) set nd6_rtrequest() to ifa->ifa_rtrequest, 156 * which changes the outgoing interface to the loopback interface. 157 */ 158 e = rtrequest(cmd, ifa->ifa_addr, ifa->ifa_addr, 159 (struct sockaddr *)&all1_sa, RTF_UP|RTF_HOST|RTF_LLINFO, &nrt); 160 if (e != 0) { 161 /* XXX need more descriptive message */ |
162 |
|
161 log(LOG_ERR, "in6_ifloop_request: " 162 "%s operation failed for %s (errno=%d)\n", 163 cmd == RTM_ADD ? "ADD" : "DELETE", | 163 log(LOG_ERR, "in6_ifloop_request: " 164 "%s operation failed for %s (errno=%d)\n", 165 cmd == RTM_ADD ? "ADD" : "DELETE", |
164 ip6_sprintf(&((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr), 165 e); | 166 ip6_sprintf(ip6buf, 167 &((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr), e); |
166 } 167 168 /* 169 * Report the addition/removal of the address to the routing socket. 170 * XXX: since we called rtinit for a p2p interface with a destination, 171 * we end up reporting twice in such a case. Should we rather 172 * omit the second report? 173 */ --- 628 unchanged lines hidden (view full) --- 802 int error = 0, hostIsNew = 0, plen = -1; 803 struct in6_ifaddr *oia; 804 struct sockaddr_in6 dst6; 805 struct in6_addrlifetime *lt; 806 struct in6_multi_mship *imm; 807 struct in6_multi *in6m_sol; 808 struct rtentry *rt; 809 int delay; | 168 } 169 170 /* 171 * Report the addition/removal of the address to the routing socket. 172 * XXX: since we called rtinit for a p2p interface with a destination, 173 * we end up reporting twice in such a case. Should we rather 174 * omit the second report? 175 */ --- 628 unchanged lines hidden (view full) --- 804 int error = 0, hostIsNew = 0, plen = -1; 805 struct in6_ifaddr *oia; 806 struct sockaddr_in6 dst6; 807 struct in6_addrlifetime *lt; 808 struct in6_multi_mship *imm; 809 struct in6_multi *in6m_sol; 810 struct rtentry *rt; 811 int delay; |
812 char ip6buf[INET6_ADDRSTRLEN]; |
|
810 811 /* Validate parameters */ 812 if (ifp == NULL || ifra == NULL) /* this maybe redundant */ 813 return (EINVAL); 814 815 /* 816 * The destination address for a p2p link must have a family 817 * of AF_UNSPEC or AF_INET6. --- 78 unchanged lines hidden (view full) --- 896 return (EINVAL); 897 if (lt->ia6t_vltime == 0) { 898 /* 899 * the following log might be noisy, but this is a typical 900 * configuration mistake or a tool's bug. 901 */ 902 nd6log((LOG_INFO, 903 "in6_update_ifa: valid lifetime is 0 for %s\n", | 813 814 /* Validate parameters */ 815 if (ifp == NULL || ifra == NULL) /* this maybe redundant */ 816 return (EINVAL); 817 818 /* 819 * The destination address for a p2p link must have a family 820 * of AF_UNSPEC or AF_INET6. --- 78 unchanged lines hidden (view full) --- 899 return (EINVAL); 900 if (lt->ia6t_vltime == 0) { 901 /* 902 * the following log might be noisy, but this is a typical 903 * configuration mistake or a tool's bug. 904 */ 905 nd6log((LOG_INFO, 906 "in6_update_ifa: valid lifetime is 0 for %s\n", |
904 ip6_sprintf(&ifra->ifra_addr.sin6_addr))); | 907 ip6_sprintf(ip6buf, &ifra->ifra_addr.sin6_addr))); |
905 906 if (ia == NULL) 907 return (0); /* there's nothing to do */ 908 } 909 910 /* 911 * If this is a new address, allocate a new ifaddr and link it 912 * into chains. --- 50 unchanged lines hidden (view full) --- 963 * address, because 964 * + such an operation should be rare in IPv6, and 965 * + the operation would confuse prefix management. 966 */ 967 if (ia->ia_prefixmask.sin6_len && 968 in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) { 969 nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an" 970 " existing (%s) address should not be changed\n", | 908 909 if (ia == NULL) 910 return (0); /* there's nothing to do */ 911 } 912 913 /* 914 * If this is a new address, allocate a new ifaddr and link it 915 * into chains. --- 50 unchanged lines hidden (view full) --- 966 * address, because 967 * + such an operation should be rare in IPv6, and 968 * + the operation would confuse prefix management. 969 */ 970 if (ia->ia_prefixmask.sin6_len && 971 in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL) != plen) { 972 nd6log((LOG_INFO, "in6_update_ifa: the prefix length of an" 973 " existing (%s) address should not be changed\n", |
971 ip6_sprintf(&ia->ia_addr.sin6_addr))); | 974 ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); |
972 error = EINVAL; 973 goto unlink; 974 } 975 ia->ia_prefixmask = ifra->ifra_prefixmask; 976 } 977 978 /* 979 * If a new destination address is specified, scrub the old one and 980 * install the new destination. Note that the interface must be 981 * p2p or loopback (see the check above.) 982 */ 983 if (dst6.sin6_family == AF_INET6 && 984 !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) { 985 int e; 986 987 if ((ia->ia_flags & IFA_ROUTE) != 0 && 988 (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) { 989 nd6log((LOG_ERR, "in6_update_ifa: failed to remove " 990 "a route to the old destination: %s\n", | 975 error = EINVAL; 976 goto unlink; 977 } 978 ia->ia_prefixmask = ifra->ifra_prefixmask; 979 } 980 981 /* 982 * If a new destination address is specified, scrub the old one and 983 * install the new destination. Note that the interface must be 984 * p2p or loopback (see the check above.) 985 */ 986 if (dst6.sin6_family == AF_INET6 && 987 !IN6_ARE_ADDR_EQUAL(&dst6.sin6_addr, &ia->ia_dstaddr.sin6_addr)) { 988 int e; 989 990 if ((ia->ia_flags & IFA_ROUTE) != 0 && 991 (e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) != 0) { 992 nd6log((LOG_ERR, "in6_update_ifa: failed to remove " 993 "a route to the old destination: %s\n", |
991 ip6_sprintf(&ia->ia_addr.sin6_addr))); | 994 ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); |
992 /* proceed anyway... */ 993 } else 994 ia->ia_flags &= ~IFA_ROUTE; 995 ia->ia_dstaddr = dst6; 996 } 997 998 /* 999 * Set lifetimes. We do not refer to ia6t_expire and ia6t_preferred --- 79 unchanged lines hidden (view full) --- 1079 delay = arc4random() % 1080 (MAX_RTR_SOLICITATION_DELAY * hz); 1081 } 1082 imm = in6_joingroup(ifp, &llsol, &error, delay); 1083 if (error != 0) { 1084 nd6log((LOG_WARNING, 1085 "in6_update_ifa: addmulti failed for " 1086 "%s on %s (errno=%d)\n", | 995 /* proceed anyway... */ 996 } else 997 ia->ia_flags &= ~IFA_ROUTE; 998 ia->ia_dstaddr = dst6; 999 } 1000 1001 /* 1002 * Set lifetimes. We do not refer to ia6t_expire and ia6t_preferred --- 79 unchanged lines hidden (view full) --- 1082 delay = arc4random() % 1083 (MAX_RTR_SOLICITATION_DELAY * hz); 1084 } 1085 imm = in6_joingroup(ifp, &llsol, &error, delay); 1086 if (error != 0) { 1087 nd6log((LOG_WARNING, 1088 "in6_update_ifa: addmulti failed for " 1089 "%s on %s (errno=%d)\n", |
1087 ip6_sprintf(&llsol), if_name(ifp), | 1090 ip6_sprintf(ip6buf, &llsol), if_name(ifp), |
1088 error)); 1089 in6_purgeaddr((struct ifaddr *)ia); 1090 return (error); 1091 } 1092 in6m_sol = imm->i6mm_maddr; 1093 1094 bzero(&mltmask, sizeof(mltmask)); 1095 mltmask.sin6_len = sizeof(struct sockaddr_in6); --- 65 unchanged lines hidden (view full) --- 1161 RTFREE_LOCKED(rt); 1162 } 1163 1164 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0); 1165 if (!imm) { 1166 nd6log((LOG_WARNING, 1167 "in6_update_ifa: addmulti failed for " 1168 "%s on %s (errno=%d)\n", | 1091 error)); 1092 in6_purgeaddr((struct ifaddr *)ia); 1093 return (error); 1094 } 1095 in6m_sol = imm->i6mm_maddr; 1096 1097 bzero(&mltmask, sizeof(mltmask)); 1098 mltmask.sin6_len = sizeof(struct sockaddr_in6); --- 65 unchanged lines hidden (view full) --- 1164 RTFREE_LOCKED(rt); 1165 } 1166 1167 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0); 1168 if (!imm) { 1169 nd6log((LOG_WARNING, 1170 "in6_update_ifa: addmulti failed for " 1171 "%s on %s (errno=%d)\n", |
1169 ip6_sprintf(&mltaddr.sin6_addr), | 1172 ip6_sprintf(ip6buf, &mltaddr.sin6_addr), |
1170 if_name(ifp), error)); 1171 goto cleanup; 1172 } 1173 1174 /* 1175 * join node information group address 1176 */ 1177#define hostnamelen strlen(hostname) --- 9 unchanged lines hidden (view full) --- 1187 if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr) 1188 == 0) { 1189 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 1190 delay); /* XXX jinmei */ 1191 if (!imm) { 1192 nd6log((LOG_WARNING, "in6_update_ifa: " 1193 "addmulti failed for %s on %s " 1194 "(errno=%d)\n", | 1173 if_name(ifp), error)); 1174 goto cleanup; 1175 } 1176 1177 /* 1178 * join node information group address 1179 */ 1180#define hostnamelen strlen(hostname) --- 9 unchanged lines hidden (view full) --- 1190 if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr) 1191 == 0) { 1192 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 1193 delay); /* XXX jinmei */ 1194 if (!imm) { 1195 nd6log((LOG_WARNING, "in6_update_ifa: " 1196 "addmulti failed for %s on %s " 1197 "(errno=%d)\n", |
1195 ip6_sprintf(&mltaddr.sin6_addr), | 1198 ip6_sprintf(ip6buf, &mltaddr.sin6_addr), |
1196 if_name(ifp), error)); 1197 /* XXX not very fatal, go on... */ 1198 } 1199 } 1200#undef hostnamelen 1201 1202 /* 1203 * join interface-local all-nodes address. --- 44 unchanged lines hidden (view full) --- 1248 RTFREE_LOCKED(rt); 1249 } 1250 1251 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0); 1252 if (!imm) { 1253 nd6log((LOG_WARNING, "in6_update_ifa: " 1254 "addmulti failed for %s on %s " 1255 "(errno=%d)\n", | 1199 if_name(ifp), error)); 1200 /* XXX not very fatal, go on... */ 1201 } 1202 } 1203#undef hostnamelen 1204 1205 /* 1206 * join interface-local all-nodes address. --- 44 unchanged lines hidden (view full) --- 1251 RTFREE_LOCKED(rt); 1252 } 1253 1254 imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, 0); 1255 if (!imm) { 1256 nd6log((LOG_WARNING, "in6_update_ifa: " 1257 "addmulti failed for %s on %s " 1258 "(errno=%d)\n", |
1256 ip6_sprintf(&mltaddr.sin6_addr), | 1259 ip6_sprintf(ip6buf, &mltaddr.sin6_addr), |
1257 if_name(ifp), error)); 1258 goto cleanup; 1259 } 1260#undef MLTMASK_LEN 1261 } 1262 1263 /* 1264 * Perform DAD, if needed. --- 50 unchanged lines hidden (view full) --- 1315} 1316 1317void 1318in6_purgeaddr(ifa) 1319 struct ifaddr *ifa; 1320{ 1321 struct ifnet *ifp = ifa->ifa_ifp; 1322 struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa; | 1260 if_name(ifp), error)); 1261 goto cleanup; 1262 } 1263#undef MLTMASK_LEN 1264 } 1265 1266 /* 1267 * Perform DAD, if needed. --- 50 unchanged lines hidden (view full) --- 1318} 1319 1320void 1321in6_purgeaddr(ifa) 1322 struct ifaddr *ifa; 1323{ 1324 struct ifnet *ifp = ifa->ifa_ifp; 1325 struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa; |
1326 char ip6buf[INET6_ADDRSTRLEN]; |
|
1323 1324 /* stop DAD processing */ 1325 nd6_dad_stop(ifa); 1326 1327 /* 1328 * delete route to the destination of the address being purged. 1329 * The interface must be p2p or loopback in this case. 1330 */ 1331 if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) { 1332 int e; 1333 1334 if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) 1335 != 0) { 1336 log(LOG_ERR, "in6_purgeaddr: failed to remove " 1337 "a route to the p2p destination: %s on %s, " 1338 "errno=%d\n", | 1327 1328 /* stop DAD processing */ 1329 nd6_dad_stop(ifa); 1330 1331 /* 1332 * delete route to the destination of the address being purged. 1333 * The interface must be p2p or loopback in this case. 1334 */ 1335 if ((ia->ia_flags & IFA_ROUTE) != 0 && ia->ia_dstaddr.sin6_len != 0) { 1336 int e; 1337 1338 if ((e = rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST)) 1339 != 0) { 1340 log(LOG_ERR, "in6_purgeaddr: failed to remove " 1341 "a route to the p2p destination: %s on %s, " 1342 "errno=%d\n", |
1339 ip6_sprintf(&ia->ia_addr.sin6_addr), if_name(ifp), 1340 e); | 1343 ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), 1344 if_name(ifp), e); |
1341 /* proceed anyway... */ 1342 } else 1343 ia->ia_flags &= ~IFA_ROUTE; 1344 } 1345 1346 /* Remove ownaddr's loopback rtentry, if it exists. */ 1347 in6_ifremloop(&(ia->ia_ifa)); 1348 --- 535 unchanged lines hidden (view full) --- 1884 if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) 1885 break; 1886 } 1887 1888 return ((struct in6_ifaddr *)ifa); 1889} 1890 1891/* | 1345 /* proceed anyway... */ 1346 } else 1347 ia->ia_flags &= ~IFA_ROUTE; 1348 } 1349 1350 /* Remove ownaddr's loopback rtentry, if it exists. */ 1351 in6_ifremloop(&(ia->ia_ifa)); 1352 --- 535 unchanged lines hidden (view full) --- 1888 if (IN6_ARE_ADDR_EQUAL(addr, IFA_IN6(ifa))) 1889 break; 1890 } 1891 1892 return ((struct in6_ifaddr *)ifa); 1893} 1894 1895/* |
1892 * Convert IP6 address to printable (loggable) representation. | 1896 * Convert IP6 address to printable (loggable) representation. Caller 1897 * has to make sure that ip6buf is at least INET6_ADDRSTRLEN long. |
1893 */ 1894static char digits[] = "0123456789abcdef"; | 1898 */ 1899static char digits[] = "0123456789abcdef"; |
1895static int ip6round = 0; | |
1896char * | 1900char * |
1897ip6_sprintf(addr) 1898 const struct in6_addr *addr; | 1901ip6_sprintf(char *ip6buf, const struct in6_addr *addr) |
1899{ | 1902{ |
1900 static char ip6buf[8][48]; | |
1901 int i; 1902 char *cp; 1903 const u_int16_t *a = (const u_int16_t *)addr; 1904 const u_int8_t *d; 1905 int dcolon = 0; 1906 | 1903 int i; 1904 char *cp; 1905 const u_int16_t *a = (const u_int16_t *)addr; 1906 const u_int8_t *d; 1907 int dcolon = 0; 1908 |
1907 ip6round = (ip6round + 1) & 7; 1908 cp = ip6buf[ip6round]; | 1909 cp = ip6buf; |
1909 1910 for (i = 0; i < 8; i++) { 1911 if (dcolon == 1) { 1912 if (*a == 0) { 1913 if (i == 7) 1914 *cp++ = ':'; 1915 a++; 1916 continue; --- 16 unchanged lines hidden (view full) --- 1933 d = (const u_char *)a; 1934 *cp++ = digits[*d >> 4]; 1935 *cp++ = digits[*d++ & 0xf]; 1936 *cp++ = digits[*d >> 4]; 1937 *cp++ = digits[*d & 0xf]; 1938 *cp++ = ':'; 1939 a++; 1940 } | 1910 1911 for (i = 0; i < 8; i++) { 1912 if (dcolon == 1) { 1913 if (*a == 0) { 1914 if (i == 7) 1915 *cp++ = ':'; 1916 a++; 1917 continue; --- 16 unchanged lines hidden (view full) --- 1934 d = (const u_char *)a; 1935 *cp++ = digits[*d >> 4]; 1936 *cp++ = digits[*d++ & 0xf]; 1937 *cp++ = digits[*d >> 4]; 1938 *cp++ = digits[*d & 0xf]; 1939 *cp++ = ':'; 1940 a++; 1941 } |
1941 *--cp = 0; 1942 return (ip6buf[ip6round]); | 1942 *--cp = '\0'; 1943 return (ip6buf); |
1943} 1944 1945int 1946in6_localaddr(in6) 1947 struct in6_addr *in6; 1948{ 1949 struct in6_ifaddr *ia; 1950 --- 438 unchanged lines hidden --- | 1944} 1945 1946int 1947in6_localaddr(in6) 1948 struct in6_addr *in6; 1949{ 1950 struct in6_ifaddr *ia; 1951 --- 438 unchanged lines hidden --- |