Deleted Added
full compact
nd6_rtr.c (160981) nd6_rtr.c (165118)
1/* $FreeBSD: head/sys/netinet6/nd6_rtr.c 160981 2006-08-04 21:27:40Z brooks $ */
1/* $FreeBSD: head/sys/netinet6/nd6_rtr.c 165118 2006-12-12 12:17:58Z bz $ */
2/* $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei 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

--- 110 unchanged lines hidden (view full) ---

120{
121 struct ifnet *ifp = m->m_pkthdr.rcvif;
122 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
123 struct nd_router_solicit *nd_rs;
124 struct in6_addr saddr6 = ip6->ip6_src;
125 char *lladdr = NULL;
126 int lladdrlen = 0;
127 union nd_opts ndopts;
2/* $KAME: nd6_rtr.c,v 1.111 2001/04/27 01:37:15 jinmei 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

--- 110 unchanged lines hidden (view full) ---

120{
121 struct ifnet *ifp = m->m_pkthdr.rcvif;
122 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
123 struct nd_router_solicit *nd_rs;
124 struct in6_addr saddr6 = ip6->ip6_src;
125 char *lladdr = NULL;
126 int lladdrlen = 0;
127 union nd_opts ndopts;
128 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
128
129 /* If I'm not a router, ignore it. */
130 if (ip6_accept_rtadv != 0 || ip6_forwarding != 1)
131 goto freeit;
132
133 /* Sanity checks */
134 if (ip6->ip6_hlim != 255) {
135 nd6log((LOG_ERR,
136 "nd6_rs_input: invalid hlim (%d) from %s to %s on %s\n",
129
130 /* If I'm not a router, ignore it. */
131 if (ip6_accept_rtadv != 0 || ip6_forwarding != 1)
132 goto freeit;
133
134 /* Sanity checks */
135 if (ip6->ip6_hlim != 255) {
136 nd6log((LOG_ERR,
137 "nd6_rs_input: invalid hlim (%d) from %s to %s on %s\n",
137 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
138 ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
138 ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
139 ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
139 goto bad;
140 }
141
142 /*
143 * Don't update the neighbor cache, if src = ::.
144 * This indicates that the src has no IP address assigned yet.
145 */
146 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))

--- 23 unchanged lines hidden (view full) ---

170 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
171 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
172 }
173
174 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
175 nd6log((LOG_INFO,
176 "nd6_rs_input: lladdrlen mismatch for %s "
177 "(if %d, RS packet %d)\n",
140 goto bad;
141 }
142
143 /*
144 * Don't update the neighbor cache, if src = ::.
145 * This indicates that the src has no IP address assigned yet.
146 */
147 if (IN6_IS_ADDR_UNSPECIFIED(&saddr6))

--- 23 unchanged lines hidden (view full) ---

171 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
172 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
173 }
174
175 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
176 nd6log((LOG_INFO,
177 "nd6_rs_input: lladdrlen mismatch for %s "
178 "(if %d, RS packet %d)\n",
178 ip6_sprintf(&saddr6),
179 ip6_sprintf(ip6bufs, &saddr6),
179 ifp->if_addrlen, lladdrlen - 2));
180 goto bad;
181 }
182
183 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
184
185 freeit:
186 m_freem(m);

--- 19 unchanged lines hidden (view full) ---

206 struct ifnet *ifp = m->m_pkthdr.rcvif;
207 struct nd_ifinfo *ndi = ND_IFINFO(ifp);
208 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
209 struct nd_router_advert *nd_ra;
210 struct in6_addr saddr6 = ip6->ip6_src;
211 int mcast = 0;
212 union nd_opts ndopts;
213 struct nd_defrouter *dr;
180 ifp->if_addrlen, lladdrlen - 2));
181 goto bad;
182 }
183
184 nd6_cache_lladdr(ifp, &saddr6, lladdr, lladdrlen, ND_ROUTER_SOLICIT, 0);
185
186 freeit:
187 m_freem(m);

--- 19 unchanged lines hidden (view full) ---

207 struct ifnet *ifp = m->m_pkthdr.rcvif;
208 struct nd_ifinfo *ndi = ND_IFINFO(ifp);
209 struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
210 struct nd_router_advert *nd_ra;
211 struct in6_addr saddr6 = ip6->ip6_src;
212 int mcast = 0;
213 union nd_opts ndopts;
214 struct nd_defrouter *dr;
215 char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
214
215 /*
216 * We only accept RAs only when
217 * the system-wide variable allows the acceptance, and
218 * per-interface variable allows RAs on the receiving interface.
219 */
220 if (ip6_accept_rtadv == 0)
221 goto freeit;
222 if (!(ndi->flags & ND6_IFF_ACCEPT_RTADV))
223 goto freeit;
224
225 if (ip6->ip6_hlim != 255) {
226 nd6log((LOG_ERR,
227 "nd6_ra_input: invalid hlim (%d) from %s to %s on %s\n",
216
217 /*
218 * We only accept RAs only when
219 * the system-wide variable allows the acceptance, and
220 * per-interface variable allows RAs on the receiving interface.
221 */
222 if (ip6_accept_rtadv == 0)
223 goto freeit;
224 if (!(ndi->flags & ND6_IFF_ACCEPT_RTADV))
225 goto freeit;
226
227 if (ip6->ip6_hlim != 255) {
228 nd6log((LOG_ERR,
229 "nd6_ra_input: invalid hlim (%d) from %s to %s on %s\n",
228 ip6->ip6_hlim, ip6_sprintf(&ip6->ip6_src),
229 ip6_sprintf(&ip6->ip6_dst), if_name(ifp)));
230 ip6->ip6_hlim, ip6_sprintf(ip6bufs, &ip6->ip6_src),
231 ip6_sprintf(ip6bufd, &ip6->ip6_dst), if_name(ifp)));
230 goto bad;
231 }
232
233 if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
234 nd6log((LOG_ERR,
235 "nd6_ra_input: src %s is not link-local\n",
232 goto bad;
233 }
234
235 if (!IN6_IS_ADDR_LINKLOCAL(&saddr6)) {
236 nd6log((LOG_ERR,
237 "nd6_ra_input: src %s is not link-local\n",
236 ip6_sprintf(&saddr6)));
238 ip6_sprintf(ip6bufs, &saddr6)));
237 goto bad;
238 }
239
240#ifndef PULLDOWN_TEST
241 IP6_EXTHDR_CHECK(m, off, icmp6len,);
242 nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);
243#else
244 IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);

--- 75 unchanged lines hidden (view full) ---

320 continue;
321 }
322
323 if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
324 || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
325 nd6log((LOG_INFO,
326 "nd6_ra_input: invalid prefix "
327 "%s, ignored\n",
239 goto bad;
240 }
241
242#ifndef PULLDOWN_TEST
243 IP6_EXTHDR_CHECK(m, off, icmp6len,);
244 nd_ra = (struct nd_router_advert *)((caddr_t)ip6 + off);
245#else
246 IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);

--- 75 unchanged lines hidden (view full) ---

322 continue;
323 }
324
325 if (IN6_IS_ADDR_MULTICAST(&pi->nd_opt_pi_prefix)
326 || IN6_IS_ADDR_LINKLOCAL(&pi->nd_opt_pi_prefix)) {
327 nd6log((LOG_INFO,
328 "nd6_ra_input: invalid prefix "
329 "%s, ignored\n",
328 ip6_sprintf(&pi->nd_opt_pi_prefix)));
330 ip6_sprintf(ip6bufs,
331 &pi->nd_opt_pi_prefix)));
329 continue;
330 }
331
332 bzero(&pr, sizeof(pr));
333 pr.ndpr_prefix.sin6_family = AF_INET6;
334 pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
335 pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
336 pr.ndpr_ifp = (struct ifnet *)m->m_pkthdr.rcvif;

--- 17 unchanged lines hidden (view full) ---

354 u_long maxmtu;
355
356 mtu = (u_long)ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
357
358 /* lower bound */
359 if (mtu < IPV6_MMTU) {
360 nd6log((LOG_INFO, "nd6_ra_input: bogus mtu option "
361 "mtu=%lu sent from %s, ignoring\n",
332 continue;
333 }
334
335 bzero(&pr, sizeof(pr));
336 pr.ndpr_prefix.sin6_family = AF_INET6;
337 pr.ndpr_prefix.sin6_len = sizeof(pr.ndpr_prefix);
338 pr.ndpr_prefix.sin6_addr = pi->nd_opt_pi_prefix;
339 pr.ndpr_ifp = (struct ifnet *)m->m_pkthdr.rcvif;

--- 17 unchanged lines hidden (view full) ---

357 u_long maxmtu;
358
359 mtu = (u_long)ntohl(ndopts.nd_opts_mtu->nd_opt_mtu_mtu);
360
361 /* lower bound */
362 if (mtu < IPV6_MMTU) {
363 nd6log((LOG_INFO, "nd6_ra_input: bogus mtu option "
364 "mtu=%lu sent from %s, ignoring\n",
362 mtu, ip6_sprintf(&ip6->ip6_src)));
365 mtu, ip6_sprintf(ip6bufs, &ip6->ip6_src)));
363 goto skip;
364 }
365
366 /* upper bound */
367 maxmtu = (ndi->maxmtu && ndi->maxmtu < ifp->if_mtu)
368 ? ndi->maxmtu : ifp->if_mtu;
369 if (mtu <= maxmtu) {
370 int change = (ndi->linkmtu != mtu);
371
372 ndi->linkmtu = mtu;
373 if (change) /* in6_maxmtu may change */
374 in6_setmaxmtu();
375 } else {
376 nd6log((LOG_INFO, "nd6_ra_input: bogus mtu "
377 "mtu=%lu sent from %s; "
378 "exceeds maxmtu %lu, ignoring\n",
366 goto skip;
367 }
368
369 /* upper bound */
370 maxmtu = (ndi->maxmtu && ndi->maxmtu < ifp->if_mtu)
371 ? ndi->maxmtu : ifp->if_mtu;
372 if (mtu <= maxmtu) {
373 int change = (ndi->linkmtu != mtu);
374
375 ndi->linkmtu = mtu;
376 if (change) /* in6_maxmtu may change */
377 in6_setmaxmtu();
378 } else {
379 nd6log((LOG_INFO, "nd6_ra_input: bogus mtu "
380 "mtu=%lu sent from %s; "
381 "exceeds maxmtu %lu, ignoring\n",
379 mtu, ip6_sprintf(&ip6->ip6_src), maxmtu));
382 mtu, ip6_sprintf(ip6bufs, &ip6->ip6_src), maxmtu));
380 }
381 }
382
383 skip:
384
385 /*
386 * Source link layer address
387 */

--- 4 unchanged lines hidden (view full) ---

392 if (ndopts.nd_opts_src_lladdr) {
393 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
394 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
395 }
396
397 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
398 nd6log((LOG_INFO,
399 "nd6_ra_input: lladdrlen mismatch for %s "
383 }
384 }
385
386 skip:
387
388 /*
389 * Source link layer address
390 */

--- 4 unchanged lines hidden (view full) ---

395 if (ndopts.nd_opts_src_lladdr) {
396 lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
397 lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
398 }
399
400 if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
401 nd6log((LOG_INFO,
402 "nd6_ra_input: lladdrlen mismatch for %s "
400 "(if %d, RA packet %d)\n", ip6_sprintf(&saddr6),
403 "(if %d, RA packet %d)\n", ip6_sprintf(ip6bufs, &saddr6),
401 ifp->if_addrlen, lladdrlen - 2));
402 goto bad;
403 }
404
405 nd6_cache_lladdr(ifp, &saddr6, lladdr,
406 lladdrlen, ND_ROUTER_ADVERT, 0);
407
408 /*

--- 465 unchanged lines hidden (view full) ---

874nd6_prelist_add(pr, dr, newp)
875 struct nd_prefixctl *pr;
876 struct nd_prefix **newp;
877 struct nd_defrouter *dr;
878{
879 struct nd_prefix *new = NULL;
880 int error = 0;
881 int i, s;
404 ifp->if_addrlen, lladdrlen - 2));
405 goto bad;
406 }
407
408 nd6_cache_lladdr(ifp, &saddr6, lladdr,
409 lladdrlen, ND_ROUTER_ADVERT, 0);
410
411 /*

--- 465 unchanged lines hidden (view full) ---

877nd6_prelist_add(pr, dr, newp)
878 struct nd_prefixctl *pr;
879 struct nd_prefix **newp;
880 struct nd_defrouter *dr;
881{
882 struct nd_prefix *new = NULL;
883 int error = 0;
884 int i, s;
885 char ip6buf[INET6_ADDRSTRLEN];
882
883 new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
884 if (new == NULL)
885 return(ENOMEM);
886 bzero(new, sizeof(*new));
887 new->ndpr_ifp = pr->ndpr_ifp;
888 new->ndpr_prefix = pr->ndpr_prefix;
889 new->ndpr_plen = pr->ndpr_plen;

--- 23 unchanged lines hidden (view full) ---

913
914 /* ND_OPT_PI_FLAG_ONLINK processing */
915 if (new->ndpr_raf_onlink) {
916 int e;
917
918 if ((e = nd6_prefix_onlink(new)) != 0) {
919 nd6log((LOG_ERR, "nd6_prelist_add: failed to make "
920 "the prefix %s/%d on-link on %s (errno=%d)\n",
886
887 new = (struct nd_prefix *)malloc(sizeof(*new), M_IP6NDP, M_NOWAIT);
888 if (new == NULL)
889 return(ENOMEM);
890 bzero(new, sizeof(*new));
891 new->ndpr_ifp = pr->ndpr_ifp;
892 new->ndpr_prefix = pr->ndpr_prefix;
893 new->ndpr_plen = pr->ndpr_plen;

--- 23 unchanged lines hidden (view full) ---

917
918 /* ND_OPT_PI_FLAG_ONLINK processing */
919 if (new->ndpr_raf_onlink) {
920 int e;
921
922 if ((e = nd6_prefix_onlink(new)) != 0) {
923 nd6log((LOG_ERR, "nd6_prelist_add: failed to make "
924 "the prefix %s/%d on-link on %s (errno=%d)\n",
921 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
925 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
922 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
923 /* proceed anyway. XXX: is it correct? */
924 }
925 }
926
927 if (dr)
928 pfxrtr_add(new, dr);
929
930 return 0;
931}
932
933void
934prelist_remove(pr)
935 struct nd_prefix *pr;
936{
937 struct nd_pfxrouter *pfr, *next;
938 int e, s;
926 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
927 /* proceed anyway. XXX: is it correct? */
928 }
929 }
930
931 if (dr)
932 pfxrtr_add(new, dr);
933
934 return 0;
935}
936
937void
938prelist_remove(pr)
939 struct nd_prefix *pr;
940{
941 struct nd_pfxrouter *pfr, *next;
942 int e, s;
943 char ip6buf[INET6_ADDRSTRLEN];
939
940 /* make sure to invalidate the prefix until it is really freed. */
941 pr->ndpr_vltime = 0;
942 pr->ndpr_pltime = 0;
943
944 /*
945 * Though these flags are now meaningless, we'd rather keep the value
946 * of pr->ndpr_raf_onlink and pr->ndpr_raf_auto not to confuse users
947 * when executing "ndp -p".
948 */
949
950 if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 &&
951 (e = nd6_prefix_offlink(pr)) != 0) {
952 nd6log((LOG_ERR, "prelist_remove: failed to make %s/%d offlink "
953 "on %s, errno=%d\n",
944
945 /* make sure to invalidate the prefix until it is really freed. */
946 pr->ndpr_vltime = 0;
947 pr->ndpr_pltime = 0;
948
949 /*
950 * Though these flags are now meaningless, we'd rather keep the value
951 * of pr->ndpr_raf_onlink and pr->ndpr_raf_auto not to confuse users
952 * when executing "ndp -p".
953 */
954
955 if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0 &&
956 (e = nd6_prefix_offlink(pr)) != 0) {
957 nd6log((LOG_ERR, "prelist_remove: failed to make %s/%d offlink "
958 "on %s, errno=%d\n",
954 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
959 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
955 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
956 /* what should we do? */
957 }
958
959 if (pr->ndpr_refcnt > 0)
960 return; /* notice here? */
961
962 s = splnet();

--- 25 unchanged lines hidden (view full) ---

988 struct ifaddr *ifa;
989 struct ifnet *ifp = new->ndpr_ifp;
990 struct nd_prefix *pr;
991 int s = splnet();
992 int error = 0;
993 int newprefix = 0;
994 int auth;
995 struct in6_addrlifetime lt6_tmp;
960 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
961 /* what should we do? */
962 }
963
964 if (pr->ndpr_refcnt > 0)
965 return; /* notice here? */
966
967 s = splnet();

--- 25 unchanged lines hidden (view full) ---

993 struct ifaddr *ifa;
994 struct ifnet *ifp = new->ndpr_ifp;
995 struct nd_prefix *pr;
996 int s = splnet();
997 int error = 0;
998 int newprefix = 0;
999 int auth;
1000 struct in6_addrlifetime lt6_tmp;
1001 char ip6buf[INET6_ADDRSTRLEN];
996
997 auth = 0;
998 if (m) {
999 /*
1000 * Authenticity for NA consists authentication for
1001 * both IP header and IP datagrams, doesn't it ?
1002 */
1003#if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)

--- 28 unchanged lines hidden (view full) ---

1032 (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1033 int e;
1034
1035 if ((e = nd6_prefix_onlink(pr)) != 0) {
1036 nd6log((LOG_ERR,
1037 "prelist_update: failed to make "
1038 "the prefix %s/%d on-link on %s "
1039 "(errno=%d)\n",
1002
1003 auth = 0;
1004 if (m) {
1005 /*
1006 * Authenticity for NA consists authentication for
1007 * both IP header and IP datagrams, doesn't it ?
1008 */
1009#if defined(M_AUTHIPHDR) && defined(M_AUTHIPDGM)

--- 28 unchanged lines hidden (view full) ---

1038 (pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1039 int e;
1040
1041 if ((e = nd6_prefix_onlink(pr)) != 0) {
1042 nd6log((LOG_ERR,
1043 "prelist_update: failed to make "
1044 "the prefix %s/%d on-link on %s "
1045 "(errno=%d)\n",
1040 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1046 ip6_sprintf(ip6buf,
1047 &pr->ndpr_prefix.sin6_addr),
1041 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
1042 /* proceed anyway. XXX: is it correct? */
1043 }
1044 }
1045
1046 if (dr && pfxrtr_lookup(pr, dr) == NULL)
1047 pfxrtr_add(pr, dr);
1048 } else {

--- 6 unchanged lines hidden (view full) ---

1055 if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0)
1056 goto end;
1057
1058 error = nd6_prelist_add(new, dr, &newpr);
1059 if (error != 0 || newpr == NULL) {
1060 nd6log((LOG_NOTICE, "prelist_update: "
1061 "nd6_prelist_add failed for %s/%d on %s "
1062 "errno=%d, returnpr=%p\n",
1048 pr->ndpr_plen, if_name(pr->ndpr_ifp), e));
1049 /* proceed anyway. XXX: is it correct? */
1050 }
1051 }
1052
1053 if (dr && pfxrtr_lookup(pr, dr) == NULL)
1054 pfxrtr_add(pr, dr);
1055 } else {

--- 6 unchanged lines hidden (view full) ---

1062 if (new->ndpr_raf_onlink == 0 && new->ndpr_raf_auto == 0)
1063 goto end;
1064
1065 error = nd6_prelist_add(new, dr, &newpr);
1066 if (error != 0 || newpr == NULL) {
1067 nd6log((LOG_NOTICE, "prelist_update: "
1068 "nd6_prelist_add failed for %s/%d on %s "
1069 "errno=%d, returnpr=%p\n",
1063 ip6_sprintf(&new->ndpr_prefix.sin6_addr),
1070 ip6_sprintf(ip6buf, &new->ndpr_prefix.sin6_addr),
1064 new->ndpr_plen, if_name(new->ndpr_ifp),
1065 error, newpr));
1066 goto end; /* we should just give up in this case. */
1067 }
1068
1069 /*
1070 * XXX: from the ND point of view, we can ignore a prefix
1071 * with the on-link bit being zero. However, we need a

--- 361 unchanged lines hidden (view full) ---

1433 * prefix, and reinstall the interface route for a (just) attached
1434 * prefix. Note that all attempt of reinstallation does not
1435 * necessarily success, when a same prefix is shared among multiple
1436 * interfaces. Such cases will be handled in nd6_prefix_onlink,
1437 * so we don't have to care about them.
1438 */
1439 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1440 int e;
1071 new->ndpr_plen, if_name(new->ndpr_ifp),
1072 error, newpr));
1073 goto end; /* we should just give up in this case. */
1074 }
1075
1076 /*
1077 * XXX: from the ND point of view, we can ignore a prefix
1078 * with the on-link bit being zero. However, we need a

--- 361 unchanged lines hidden (view full) ---

1440 * prefix, and reinstall the interface route for a (just) attached
1441 * prefix. Note that all attempt of reinstallation does not
1442 * necessarily success, when a same prefix is shared among multiple
1443 * interfaces. Such cases will be handled in nd6_prefix_onlink,
1444 * so we don't have to care about them.
1445 */
1446 for (pr = nd_prefix.lh_first; pr; pr = pr->ndpr_next) {
1447 int e;
1448 char ip6buf[INET6_ADDRSTRLEN];
1441
1442 if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1443 continue;
1444
1445 if (pr->ndpr_raf_onlink == 0)
1446 continue;
1447
1448 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
1449 (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1450 if ((e = nd6_prefix_offlink(pr)) != 0) {
1451 nd6log((LOG_ERR,
1452 "pfxlist_onlink_check: failed to "
1453 "make %s/%d offlink, errno=%d\n",
1449
1450 if (IN6_IS_ADDR_LINKLOCAL(&pr->ndpr_prefix.sin6_addr))
1451 continue;
1452
1453 if (pr->ndpr_raf_onlink == 0)
1454 continue;
1455
1456 if ((pr->ndpr_stateflags & NDPRF_DETACHED) != 0 &&
1457 (pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1458 if ((e = nd6_prefix_offlink(pr)) != 0) {
1459 nd6log((LOG_ERR,
1460 "pfxlist_onlink_check: failed to "
1461 "make %s/%d offlink, errno=%d\n",
1454 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1455 pr->ndpr_plen, e));
1462 ip6_sprintf(ip6buf,
1463 &pr->ndpr_prefix.sin6_addr),
1464 pr->ndpr_plen, e));
1456 }
1457 }
1458 if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
1459 (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
1460 pr->ndpr_raf_onlink) {
1461 if ((e = nd6_prefix_onlink(pr)) != 0) {
1462 nd6log((LOG_ERR,
1463 "pfxlist_onlink_check: failed to "
1464 "make %s/%d onlink, errno=%d\n",
1465 }
1466 }
1467 if ((pr->ndpr_stateflags & NDPRF_DETACHED) == 0 &&
1468 (pr->ndpr_stateflags & NDPRF_ONLINK) == 0 &&
1469 pr->ndpr_raf_onlink) {
1470 if ((e = nd6_prefix_onlink(pr)) != 0) {
1471 nd6log((LOG_ERR,
1472 "pfxlist_onlink_check: failed to "
1473 "make %s/%d onlink, errno=%d\n",
1465 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1466 pr->ndpr_plen, e));
1474 ip6_sprintf(ip6buf,
1475 &pr->ndpr_prefix.sin6_addr),
1476 pr->ndpr_plen, e));
1467 }
1468 }
1469 }
1470
1471 /*
1472 * Changes on the prefix status might affect address status as well.
1473 * Make sure that all addresses derived from an attached prefix are
1474 * attached, and that all addresses derived from a detached prefix are

--- 57 unchanged lines hidden (view full) ---

1532{
1533 struct ifaddr *ifa;
1534 struct ifnet *ifp = pr->ndpr_ifp;
1535 struct sockaddr_in6 mask6;
1536 struct nd_prefix *opr;
1537 u_long rtflags;
1538 int error = 0;
1539 struct rtentry *rt = NULL;
1477 }
1478 }
1479 }
1480
1481 /*
1482 * Changes on the prefix status might affect address status as well.
1483 * Make sure that all addresses derived from an attached prefix are
1484 * attached, and that all addresses derived from a detached prefix are

--- 57 unchanged lines hidden (view full) ---

1542{
1543 struct ifaddr *ifa;
1544 struct ifnet *ifp = pr->ndpr_ifp;
1545 struct sockaddr_in6 mask6;
1546 struct nd_prefix *opr;
1547 u_long rtflags;
1548 int error = 0;
1549 struct rtentry *rt = NULL;
1550 char ip6buf[INET6_ADDRSTRLEN];
1540
1541 /* sanity check */
1542 if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1543 nd6log((LOG_ERR,
1544 "nd6_prefix_onlink: %s/%d is already on-link\n",
1551
1552 /* sanity check */
1553 if ((pr->ndpr_stateflags & NDPRF_ONLINK) != 0) {
1554 nd6log((LOG_ERR,
1555 "nd6_prefix_onlink: %s/%d is already on-link\n",
1545 ip6_sprintf(&pr->ndpr_prefix.sin6_addr), pr->ndpr_plen));
1556 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
1557 pr->ndpr_plen));
1546 return (EEXIST);
1547 }
1548
1549 /*
1550 * Add the interface route associated with the prefix. Before
1551 * installing the route, check if there's the same prefix on another
1552 * interface, and the prefix has already installed the interface route.
1553 * Although such a configuration is expected to be rare, we explicitly

--- 31 unchanged lines hidden (view full) ---

1585 * This can still happen, when, for example, we receive an RA
1586 * containing a prefix with the L bit set and the A bit clear,
1587 * after removing all IPv6 addresses on the receiving
1588 * interface. This should, of course, be rare though.
1589 */
1590 nd6log((LOG_NOTICE,
1591 "nd6_prefix_onlink: failed to find any ifaddr"
1592 " to add route for a prefix(%s/%d) on %s\n",
1558 return (EEXIST);
1559 }
1560
1561 /*
1562 * Add the interface route associated with the prefix. Before
1563 * installing the route, check if there's the same prefix on another
1564 * interface, and the prefix has already installed the interface route.
1565 * Although such a configuration is expected to be rare, we explicitly

--- 31 unchanged lines hidden (view full) ---

1597 * This can still happen, when, for example, we receive an RA
1598 * containing a prefix with the L bit set and the A bit clear,
1599 * after removing all IPv6 addresses on the receiving
1600 * interface. This should, of course, be rare though.
1601 */
1602 nd6log((LOG_NOTICE,
1603 "nd6_prefix_onlink: failed to find any ifaddr"
1604 " to add route for a prefix(%s/%d) on %s\n",
1593 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1605 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
1594 pr->ndpr_plen, if_name(ifp)));
1595 return (0);
1596 }
1597
1598 /*
1599 * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
1600 * ifa->ifa_rtrequest = nd6_rtrequest;
1601 */

--- 12 unchanged lines hidden (view full) ---

1614 }
1615 error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
1616 ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
1617 if (error == 0) {
1618 if (rt != NULL) /* this should be non NULL, though */
1619 nd6_rtmsg(RTM_ADD, rt);
1620 pr->ndpr_stateflags |= NDPRF_ONLINK;
1621 } else {
1606 pr->ndpr_plen, if_name(ifp)));
1607 return (0);
1608 }
1609
1610 /*
1611 * in6_ifinit() sets nd6_rtrequest to ifa_rtrequest for all ifaddrs.
1612 * ifa->ifa_rtrequest = nd6_rtrequest;
1613 */

--- 12 unchanged lines hidden (view full) ---

1626 }
1627 error = rtrequest(RTM_ADD, (struct sockaddr *)&pr->ndpr_prefix,
1628 ifa->ifa_addr, (struct sockaddr *)&mask6, rtflags, &rt);
1629 if (error == 0) {
1630 if (rt != NULL) /* this should be non NULL, though */
1631 nd6_rtmsg(RTM_ADD, rt);
1632 pr->ndpr_stateflags |= NDPRF_ONLINK;
1633 } else {
1634 char ip6bufg[INET6_ADDRSTRLEN], ip6bufm[INET6_ADDRSTRLEN];
1622 nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
1623 " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
1624 "errno = %d\n",
1635 nd6log((LOG_ERR, "nd6_prefix_onlink: failed to add route for a"
1636 " prefix (%s/%d) on %s, gw=%s, mask=%s, flags=%lx "
1637 "errno = %d\n",
1625 ip6_sprintf(&pr->ndpr_prefix.sin6_addr),
1638 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
1626 pr->ndpr_plen, if_name(ifp),
1639 pr->ndpr_plen, if_name(ifp),
1627 ip6_sprintf(&((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
1628 ip6_sprintf(&mask6.sin6_addr), rtflags, error));
1640 ip6_sprintf(ip6bufg, &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr),
1641 ip6_sprintf(ip6bufm, &mask6.sin6_addr), rtflags, error));
1629 }
1630
1631 if (rt != NULL) {
1632 RT_LOCK(rt);
1633 RT_REMREF(rt);
1634 RT_UNLOCK(rt);
1635 }
1636

--- 4 unchanged lines hidden (view full) ---

1641nd6_prefix_offlink(pr)
1642 struct nd_prefix *pr;
1643{
1644 int error = 0;
1645 struct ifnet *ifp = pr->ndpr_ifp;
1646 struct nd_prefix *opr;
1647 struct sockaddr_in6 sa6, mask6;
1648 struct rtentry *rt = NULL;
1642 }
1643
1644 if (rt != NULL) {
1645 RT_LOCK(rt);
1646 RT_REMREF(rt);
1647 RT_UNLOCK(rt);
1648 }
1649

--- 4 unchanged lines hidden (view full) ---

1654nd6_prefix_offlink(pr)
1655 struct nd_prefix *pr;
1656{
1657 int error = 0;
1658 struct ifnet *ifp = pr->ndpr_ifp;
1659 struct nd_prefix *opr;
1660 struct sockaddr_in6 sa6, mask6;
1661 struct rtentry *rt = NULL;
1662 char ip6buf[INET6_ADDRSTRLEN];
1649
1650 /* sanity check */
1651 if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1652 nd6log((LOG_ERR,
1653 "nd6_prefix_offlink: %s/%d is already off-link\n",
1663
1664 /* sanity check */
1665 if ((pr->ndpr_stateflags & NDPRF_ONLINK) == 0) {
1666 nd6log((LOG_ERR,
1667 "nd6_prefix_offlink: %s/%d is already off-link\n",
1654 ip6_sprintf(&pr->ndpr_prefix.sin6_addr), pr->ndpr_plen));
1668 ip6_sprintf(ip6buf, &pr->ndpr_prefix.sin6_addr),
1669 pr->ndpr_plen));
1655 return (EEXIST);
1656 }
1657
1658 bzero(&sa6, sizeof(sa6));
1659 sa6.sin6_family = AF_INET6;
1660 sa6.sin6_len = sizeof(sa6);
1661 bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
1662 sizeof(struct in6_addr));

--- 36 unchanged lines hidden (view full) ---

1699 &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
1700 int e;
1701
1702 if ((e = nd6_prefix_onlink(opr)) != 0) {
1703 nd6log((LOG_ERR,
1704 "nd6_prefix_offlink: failed to "
1705 "recover a prefix %s/%d from %s "
1706 "to %s (errno = %d)\n",
1670 return (EEXIST);
1671 }
1672
1673 bzero(&sa6, sizeof(sa6));
1674 sa6.sin6_family = AF_INET6;
1675 sa6.sin6_len = sizeof(sa6);
1676 bcopy(&pr->ndpr_prefix.sin6_addr, &sa6.sin6_addr,
1677 sizeof(struct in6_addr));

--- 36 unchanged lines hidden (view full) ---

1714 &opr->ndpr_prefix.sin6_addr, pr->ndpr_plen)) {
1715 int e;
1716
1717 if ((e = nd6_prefix_onlink(opr)) != 0) {
1718 nd6log((LOG_ERR,
1719 "nd6_prefix_offlink: failed to "
1720 "recover a prefix %s/%d from %s "
1721 "to %s (errno = %d)\n",
1707 ip6_sprintf(&opr->ndpr_prefix.sin6_addr),
1722 ip6_sprintf(ip6buf,
1723 &opr->ndpr_prefix.sin6_addr),
1708 opr->ndpr_plen, if_name(ifp),
1709 if_name(opr->ndpr_ifp), e));
1710 }
1711 }
1712 }
1713 } else {
1714 /* XXX: can we still set the NDPRF_ONLINK flag? */
1715 nd6log((LOG_ERR,
1716 "nd6_prefix_offlink: failed to delete route: "
1717 "%s/%d on %s (errno = %d)\n",
1724 opr->ndpr_plen, if_name(ifp),
1725 if_name(opr->ndpr_ifp), e));
1726 }
1727 }
1728 }
1729 } else {
1730 /* XXX: can we still set the NDPRF_ONLINK flag? */
1731 nd6log((LOG_ERR,
1732 "nd6_prefix_offlink: failed to delete route: "
1733 "%s/%d on %s (errno = %d)\n",
1718 ip6_sprintf(&sa6.sin6_addr), pr->ndpr_plen, if_name(ifp),
1719 error));
1734 ip6_sprintf(ip6buf, &sa6.sin6_addr), pr->ndpr_plen,
1735 if_name(ifp), error));
1720 }
1721
1722 if (rt != NULL) {
1723 RTFREE(rt);
1724 }
1725
1726 return (error);
1727}

--- 6 unchanged lines hidden (view full) ---

1734 struct ifnet *ifp = pr->ndpr_ifp;
1735 struct ifaddr *ifa;
1736 struct in6_aliasreq ifra;
1737 struct in6_ifaddr *ia, *ib;
1738 int error, plen0;
1739 struct in6_addr mask;
1740 int prefixlen = pr->ndpr_plen;
1741 int updateflags;
1736 }
1737
1738 if (rt != NULL) {
1739 RTFREE(rt);
1740 }
1741
1742 return (error);
1743}

--- 6 unchanged lines hidden (view full) ---

1750 struct ifnet *ifp = pr->ndpr_ifp;
1751 struct ifaddr *ifa;
1752 struct in6_aliasreq ifra;
1753 struct in6_ifaddr *ia, *ib;
1754 int error, plen0;
1755 struct in6_addr mask;
1756 int prefixlen = pr->ndpr_plen;
1757 int updateflags;
1758 char ip6buf[INET6_ADDRSTRLEN];
1742
1743 in6_prefixlen2mask(&mask, prefixlen);
1744
1745 /*
1746 * find a link-local address (will be interface ID).
1747 * Is it really mandatory? Theoretically, a global or a site-local
1748 * address can be configured without a link-local address, if we
1749 * have a unique interface identifier...

--- 71 unchanged lines hidden (view full) ---

1821 /*
1822 * Make sure that we do not have this address already. This should
1823 * usually not happen, but we can still see this case, e.g., if we
1824 * have manually configured the exact address to be configured.
1825 */
1826 if (in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr) != NULL) {
1827 /* this should be rare enough to make an explicit log */
1828 log(LOG_INFO, "in6_ifadd: %s is already configured\n",
1759
1760 in6_prefixlen2mask(&mask, prefixlen);
1761
1762 /*
1763 * find a link-local address (will be interface ID).
1764 * Is it really mandatory? Theoretically, a global or a site-local
1765 * address can be configured without a link-local address, if we
1766 * have a unique interface identifier...

--- 71 unchanged lines hidden (view full) ---

1838 /*
1839 * Make sure that we do not have this address already. This should
1840 * usually not happen, but we can still see this case, e.g., if we
1841 * have manually configured the exact address to be configured.
1842 */
1843 if (in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr) != NULL) {
1844 /* this should be rare enough to make an explicit log */
1845 log(LOG_INFO, "in6_ifadd: %s is already configured\n",
1829 ip6_sprintf(&ifra.ifra_addr.sin6_addr));
1846 ip6_sprintf(ip6buf, &ifra.ifra_addr.sin6_addr));
1830 return (NULL);
1831 }
1832
1833 /*
1834 * Allocate ifaddr structure, link into chain, etc.
1835 * If we are going to create a new address upon receiving a multicasted
1836 * RA, we need to impose a random delay before starting DAD.
1837 * [draft-ietf-ipv6-rfc2462bis-02.txt, Section 5.4.2]
1838 */
1839 updateflags = 0;
1840 if (mcast)
1841 updateflags |= IN6_IFAUPDATE_DADDELAY;
1842 if ((error = in6_update_ifa(ifp, &ifra, NULL, updateflags)) != 0) {
1843 nd6log((LOG_ERR,
1844 "in6_ifadd: failed to make ifaddr %s on %s (errno=%d)\n",
1847 return (NULL);
1848 }
1849
1850 /*
1851 * Allocate ifaddr structure, link into chain, etc.
1852 * If we are going to create a new address upon receiving a multicasted
1853 * RA, we need to impose a random delay before starting DAD.
1854 * [draft-ietf-ipv6-rfc2462bis-02.txt, Section 5.4.2]
1855 */
1856 updateflags = 0;
1857 if (mcast)
1858 updateflags |= IN6_IFAUPDATE_DADDELAY;
1859 if ((error = in6_update_ifa(ifp, &ifra, NULL, updateflags)) != 0) {
1860 nd6log((LOG_ERR,
1861 "in6_ifadd: failed to make ifaddr %s on %s (errno=%d)\n",
1845 ip6_sprintf(&ifra.ifra_addr.sin6_addr), if_name(ifp),
1846 error));
1862 ip6_sprintf(ip6buf, &ifra.ifra_addr.sin6_addr),
1863 if_name(ifp), error));
1847 return (NULL); /* ifaddr must not have been allocated. */
1848 }
1849
1850 ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
1851
1852 return (ia); /* this is always non-NULL */
1853}
1854

--- 253 unchanged lines hidden ---
1864 return (NULL); /* ifaddr must not have been allocated. */
1865 }
1866
1867 ia = in6ifa_ifpwithaddr(ifp, &ifra.ifra_addr.sin6_addr);
1868
1869 return (ia); /* this is always non-NULL */
1870}
1871

--- 253 unchanged lines hidden ---