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; |
143 char ip6buf[INET6_ADDRSTRLEN]; |
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 |
163 log(LOG_ERR, "in6_ifloop_request: " 164 "%s operation failed for %s (errno=%d)\n", 165 cmd == RTM_ADD ? "ADD" : "DELETE", |
166 ip6_sprintf(ip6buf, 167 &((struct in6_ifaddr *)ifa)->ia_addr.sin6_addr), e); |
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]; |
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", |
907 ip6_sprintf(ip6buf, &ifra->ifra_addr.sin6_addr))); |
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", |
974 ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); |
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", |
994 ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr))); |
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", |
1090 ip6_sprintf(ip6buf, &llsol), if_name(ifp), |
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", |
1172 ip6_sprintf(ip6buf, &mltaddr.sin6_addr), |
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", |
1198 ip6_sprintf(ip6buf, &mltaddr.sin6_addr), |
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", |
1259 ip6_sprintf(ip6buf, &mltaddr.sin6_addr), |
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]; |
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", |
1343 ip6_sprintf(ip6buf, &ia->ia_addr.sin6_addr), 1344 if_name(ifp), e); |
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/* |
1896 * Convert IP6 address to printable (loggable) representation. Caller 1897 * has to make sure that ip6buf is at least INET6_ADDRSTRLEN long. |
1898 */ 1899static char digits[] = "0123456789abcdef"; |
1900char * |
1901ip6_sprintf(char *ip6buf, const struct in6_addr *addr) |
1902{ |
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 |
1909 cp = ip6buf; |
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 } |
1942 *--cp = '\0'; 1943 return (ip6buf); |
1944} 1945 1946int 1947in6_localaddr(in6) 1948 struct in6_addr *in6; 1949{ 1950 struct in6_ifaddr *ia; 1951 --- 438 unchanged lines hidden --- |