Deleted Added
full compact
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;
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",
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);
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",
904 ip6_sprintf(&ifra->ifra_addr.sin6_addr)));
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",
971 ip6_sprintf(&ia->ia_addr.sin6_addr)));
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",
991 ip6_sprintf(&ia->ia_addr.sin6_addr)));
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",
1087 ip6_sprintf(&llsol), if_name(ifp),
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",
1169 ip6_sprintf(&mltaddr.sin6_addr),
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",
1195 ip6_sprintf(&mltaddr.sin6_addr),
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",
1256 ip6_sprintf(&mltaddr.sin6_addr),
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",
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);
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.
1898 */
1899static char digits[] = "0123456789abcdef";
1895static int ip6round = 0;
1900char *
1897ip6_sprintf(addr)
1898 const struct in6_addr *addr;
1901ip6_sprintf(char *ip6buf, const struct in6_addr *addr)
1902{
1900 static char ip6buf[8][48];
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;
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);
1944}
1945
1946int
1947in6_localaddr(in6)
1948 struct in6_addr *in6;
1949{
1950 struct in6_ifaddr *ia;
1951

--- 438 unchanged lines hidden ---