supported IPV6_RECVPATHMTU socket option.

Obtained from:	KAME
This commit is contained in:
Hajimu UMEMOTO 2004-02-13 14:50:01 +00:00
parent 41460aa51a
commit efddf5c64d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=125776
7 changed files with 72 additions and 10 deletions

View File

@ -1192,7 +1192,7 @@ tcp6_ctlinput(cmd, sa, d)
in6_pcbnotify(&tcb, sa, th.th_dport,
(struct sockaddr *)ip6cp->ip6c_src,
th.th_sport, cmd, notify);
th.th_sport, cmd, NULL, notify);
inc.inc_fport = th.th_dport;
inc.inc_lport = th.th_sport;
@ -1202,7 +1202,7 @@ tcp6_ctlinput(cmd, sa, d)
syncache_unreach(&inc, &th);
} else
in6_pcbnotify(&tcb, sa, 0, (const struct sockaddr *)sa6_src,
0, cmd, notify);
0, cmd, NULL, notify);
}
#endif /* INET6 */

View File

@ -1192,7 +1192,7 @@ tcp6_ctlinput(cmd, sa, d)
in6_pcbnotify(&tcb, sa, th.th_dport,
(struct sockaddr *)ip6cp->ip6c_src,
th.th_sport, cmd, notify);
th.th_sport, cmd, NULL, notify);
inc.inc_fport = th.th_dport;
inc.inc_lport = th.th_sport;
@ -1202,7 +1202,7 @@ tcp6_ctlinput(cmd, sa, d)
syncache_unreach(&inc, &th);
} else
in6_pcbnotify(&tcb, sa, 0, (const struct sockaddr *)sa6_src,
0, cmd, notify);
0, cmd, NULL, notify);
}
#endif /* INET6 */

View File

@ -610,12 +610,13 @@ in6_mapped_peeraddr(struct socket *so, struct sockaddr **nam)
* Must be called at splnet.
*/
void
in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, notify)
in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, cmdarg, notify)
struct inpcbhead *head;
struct sockaddr *dst;
const struct sockaddr *src;
u_int fport_arg, lport_arg;
int cmd;
void *cmdarg;
struct inpcb *(*notify) __P((struct inpcb *, int));
{
struct inpcb *inp, *ninp;
@ -661,6 +662,22 @@ in6_pcbnotify(head, dst, fport_arg, src, lport_arg, cmd, notify)
if ((inp->inp_vflag & INP_IPV6) == 0)
continue;
/*
* If the error designates a new path MTU for a destination
* and the application (associated with this socket) wanted to
* know the value, notify. Note that we notify for all
* disconnected sockets if the corresponding application
* wanted. This is because some UDP applications keep sending
* sockets disconnected.
* XXX: should we avoid to notify the value to TCP sockets?
*/
if (cmd == PRC_MSGSIZE && (inp->inp_flags & IN6P_MTU) != 0 &&
(IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_faddr) ||
IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &sa6_dst->sin6_addr))) {
ip6_notify_pmtu(inp, (struct sockaddr_in6 *)dst,
(u_int32_t *)cmdarg);
}
/*
* Detect if we should notify the error. If no source and
* destination ports are specifed, but non-zero flowinfo and

View File

@ -91,7 +91,7 @@ struct inpcb *
struct in6_addr *, u_int, struct in6_addr *,
u_int, int, struct ifnet *));
void in6_pcbnotify __P((struct inpcbhead *, struct sockaddr *,
u_int, const struct sockaddr *, u_int, int,
u_int, const struct sockaddr *, u_int, int, void *,
struct inpcb *(*)(struct inpcb *, int)));
struct inpcb *
in6_rtchange __P((struct inpcb *, int));

View File

@ -1307,6 +1307,45 @@ ip6_savecontrol(in6p, m, mp)
#undef IS2292
}
void
ip6_notify_pmtu(in6p, dst, mtu)
struct inpcb *in6p;
struct sockaddr_in6 *dst;
u_int32_t *mtu;
{
struct socket *so;
struct mbuf *m_mtu;
struct ip6_mtuinfo mtuctl;
so = in6p->inp_socket;
if (mtu == NULL)
return;
#ifdef DIAGNOSTIC
if (so == NULL) /* I believe this is impossible */
panic("ip6_notify_pmtu: socket is NULL");
#endif
bzero(&mtuctl, sizeof(mtuctl)); /* zero-clear for safety */
mtuctl.ip6m_mtu = *mtu;
mtuctl.ip6m_addr = *dst;
in6_recoverscope(&mtuctl.ip6m_addr, &mtuctl.ip6m_addr.sin6_addr, NULL);
if ((m_mtu = sbcreatecontrol((caddr_t)&mtuctl, sizeof(mtuctl),
IPV6_PATHMTU, IPPROTO_IPV6)) == NULL)
return;
if (sbappendaddr(&so->so_rcv, (struct sockaddr *)dst, NULL, m_mtu)
== 0) {
m_freem(m_mtu);
/* XXX: should count statistics */
} else
sorwakeup(so);
return;
}
#ifdef PULLDOWN_TEST
/*
* pull single extension header from mbuf chain. returns single mbuf that

View File

@ -278,6 +278,7 @@ rip6_ctlinput(cmd, sa, d)
int off = 0;
struct ip6ctlparam *ip6cp = NULL;
const struct sockaddr_in6 *sa6_src = NULL;
void *cmdarg;
struct inpcb *(*notify) __P((struct inpcb *, int)) = in6_rtchange;
if (sa->sa_family != AF_INET6 ||
@ -299,15 +300,17 @@ rip6_ctlinput(cmd, sa, d)
m = ip6cp->ip6c_m;
ip6 = ip6cp->ip6c_ip6;
off = ip6cp->ip6c_off;
cmdarg = ip6cp->ip6c_cmdarg;
sa6_src = ip6cp->ip6c_src;
} else {
m = NULL;
ip6 = NULL;
cmdarg = NULL;
sa6_src = &sa6_any;
}
(void) in6_pcbnotify(&ripcb, sa, 0, (const struct sockaddr *)sa6_src,
0, cmd, notify);
0, cmd, cmdarg, notify);
}
/*

View File

@ -435,6 +435,7 @@ udp6_ctlinput(cmd, sa, d)
int off = 0;
struct ip6ctlparam *ip6cp = NULL;
const struct sockaddr_in6 *sa6_src = NULL;
void *cmdarg;
struct inpcb *(*notify) __P((struct inpcb *, int)) = udp_notify;
struct udp_portonly {
u_int16_t uh_sport;
@ -460,10 +461,12 @@ udp6_ctlinput(cmd, sa, d)
m = ip6cp->ip6c_m;
ip6 = ip6cp->ip6c_ip6;
off = ip6cp->ip6c_off;
cmdarg = ip6cp->ip6c_cmdarg;
sa6_src = ip6cp->ip6c_src;
} else {
m = NULL;
ip6 = NULL;
cmdarg = NULL;
sa6_src = &sa6_any;
}
@ -481,12 +484,12 @@ udp6_ctlinput(cmd, sa, d)
m_copydata(m, off, sizeof(*uhp), (caddr_t)&uh);
(void) in6_pcbnotify(&udb, sa, uh.uh_dport,
(struct sockaddr *)ip6cp->ip6c_src,
uh.uh_sport, cmd, notify);
(struct sockaddr *)ip6cp->ip6c_src,
uh.uh_sport, cmd, cmdarg, notify);
} else
(void) in6_pcbnotify(&udb, sa, 0,
(const struct sockaddr *)sa6_src,
0, cmd, notify);
0, cmd, cmdarg, notify);
}
static int