summaryrefslogtreecommitdiffstats
path: root/sys/netinet6
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2005-07-21 16:39:23 +0000
committerume <ume@FreeBSD.org>2005-07-21 16:39:23 +0000
commit5960d35adee19b10a49567b65b0b57a4adc077bd (patch)
treea81f09d3e50491f99269ba11de9c7df1e790a970 /sys/netinet6
parent3969c485d9ac072bb7cc40918d3bf4c463ead835 (diff)
downloadFreeBSD-src-5960d35adee19b10a49567b65b0b57a4adc077bd.zip
FreeBSD-src-5960d35adee19b10a49567b65b0b57a4adc077bd.tar.gz
always copy ip6_pktopt. remove needcopy and needfree
argument/structure member accordingly. Submitted by: Keiichi SHIMA <keiichi__at__iijlab.net> Obtained from: KAME
Diffstat (limited to 'sys/netinet6')
-rw-r--r--sys/netinet6/ip6_output.c134
-rw-r--r--sys/netinet6/ip6_var.h4
-rw-r--r--sys/netinet6/raw_ip6.c2
-rw-r--r--sys/netinet6/udp6_output.c2
4 files changed, 67 insertions, 75 deletions
diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c
index a9ffbef..bee369e 100644
--- a/sys/netinet6/ip6_output.c
+++ b/sys/netinet6/ip6_output.c
@@ -139,6 +139,7 @@ static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t));
static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *));
static int ip6_getpmtu __P((struct route_in6 *, struct route_in6 *,
struct ifnet *, struct in6_addr *, u_long *, int *));
+static int copypktopts __P((struct ip6_pktopts *, struct ip6_pktopts *, int));
/*
@@ -2358,7 +2359,7 @@ ip6_pcbopts(pktopt, m, so, sopt)
/* set options specified by user. */
if (td && !suser(td))
priv = 1;
- if ((error = ip6_setpktopts(m, opt, NULL, priv, 1,
+ if ((error = ip6_setpktopts(m, opt, NULL, priv,
so->so_proto->pr_protocol)) != 0) {
ip6_clearpktopts(opt, -1); /* XXX: discard all options */
free(opt, M_IP6OPT);
@@ -2397,7 +2398,6 @@ ip6_pcbopt(optname, buf, len, pktopt, priv, uproto)
*pktopt = malloc(sizeof(struct ip6_pktopts), M_IP6OPT,
M_WAITOK);
ip6_initpktopts(*pktopt);
- (*pktopt)->needfree = 1;
}
opt = *pktopt;
@@ -2510,15 +2510,11 @@ ip6_clearpktopts(pktopt, optname)
struct ip6_pktopts *pktopt;
int optname;
{
- int needfree;
-
if (pktopt == NULL)
return;
- needfree = pktopt->needfree;
-
if (optname == -1 || optname == IPV6_PKTINFO) {
- if (needfree && pktopt->ip6po_pktinfo)
+ if (pktopt->ip6po_pktinfo)
free(pktopt->ip6po_pktinfo, M_IP6OPT);
pktopt->ip6po_pktinfo = NULL;
}
@@ -2531,22 +2527,22 @@ ip6_clearpktopts(pktopt, optname)
RTFREE(pktopt->ip6po_nextroute.ro_rt);
pktopt->ip6po_nextroute.ro_rt = NULL;
}
- if (needfree && pktopt->ip6po_nexthop)
+ if (pktopt->ip6po_nexthop)
free(pktopt->ip6po_nexthop, M_IP6OPT);
pktopt->ip6po_nexthop = NULL;
}
if (optname == -1 || optname == IPV6_HOPOPTS) {
- if (needfree && pktopt->ip6po_hbh)
+ if (pktopt->ip6po_hbh)
free(pktopt->ip6po_hbh, M_IP6OPT);
pktopt->ip6po_hbh = NULL;
}
if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) {
- if (needfree && pktopt->ip6po_dest1)
+ if (pktopt->ip6po_dest1)
free(pktopt->ip6po_dest1, M_IP6OPT);
pktopt->ip6po_dest1 = NULL;
}
if (optname == -1 || optname == IPV6_RTHDR) {
- if (needfree && pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
+ if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
free(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT);
pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL;
if (pktopt->ip6po_route.ro_rt) {
@@ -2555,7 +2551,7 @@ ip6_clearpktopts(pktopt, optname)
}
}
if (optname == -1 || optname == IPV6_DSTOPTS) {
- if (needfree && pktopt->ip6po_dest2)
+ if (pktopt->ip6po_dest2)
free(pktopt->ip6po_dest2, M_IP6OPT);
pktopt->ip6po_dest2 = NULL;
}
@@ -2572,24 +2568,16 @@ do {\
}\
} while (/*CONSTCOND*/ 0)
-struct ip6_pktopts *
-ip6_copypktopts(src, canwait)
- struct ip6_pktopts *src;
+static int
+copypktopts(dst, src, canwait)
+ struct ip6_pktopts *dst, *src;
int canwait;
{
- struct ip6_pktopts *dst;
-
- if (src == NULL) {
+ if (dst == NULL || src == NULL) {
printf("ip6_clearpktopts: invalid argument\n");
- return (NULL);
+ return (EINVAL);
}
- dst = malloc(sizeof(*dst), M_IP6OPT, canwait);
- if (dst == NULL && canwait == M_NOWAIT)
- return (NULL);
- bzero(dst, sizeof(*dst));
- dst->needfree = 1;
-
dst->ip6po_hlim = src->ip6po_hlim;
dst->ip6po_tclass = src->ip6po_tclass;
dst->ip6po_flags = src->ip6po_flags;
@@ -2612,7 +2600,7 @@ ip6_copypktopts(src, canwait)
PKTOPT_EXTHDRCPY(ip6po_dest1);
PKTOPT_EXTHDRCPY(ip6po_dest2);
PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */
- return (dst);
+ return (0);
bad:
if (dst->ip6po_pktinfo) free(dst->ip6po_pktinfo, M_IP6OPT);
@@ -2621,11 +2609,31 @@ ip6_copypktopts(src, canwait)
if (dst->ip6po_dest1) free(dst->ip6po_dest1, M_IP6OPT);
if (dst->ip6po_dest2) free(dst->ip6po_dest2, M_IP6OPT);
if (dst->ip6po_rthdr) free(dst->ip6po_rthdr, M_IP6OPT);
- free(dst, M_IP6OPT);
- return (NULL);
+ return (ENOBUFS);
}
#undef PKTOPT_EXTHDRCPY
+struct ip6_pktopts *
+ip6_copypktopts(src, canwait)
+ struct ip6_pktopts *src;
+ int canwait;
+{
+ int error;
+ struct ip6_pktopts *dst;
+
+ dst = malloc(sizeof(*dst), M_IP6OPT, canwait);
+ if (dst == NULL && canwait == M_NOWAIT)
+ return (NULL);
+ ip6_initpktopts(dst);
+
+ if ((error = copypktopts(dst, src, canwait)) != 0) {
+ free(dst, M_IP6OPT);
+ return (NULL);
+ }
+
+ return (dst);
+}
+
void
ip6_freepcbopts(pktopt)
struct ip6_pktopts *pktopt;
@@ -2998,33 +3006,32 @@ ip6_freemoptions(im6o)
* Set IPv6 outgoing packet options based on advanced API.
*/
int
-ip6_setpktopts(control, opt, stickyopt, priv, needcopy, uproto)
+ip6_setpktopts(control, opt, stickyopt, priv, uproto)
struct mbuf *control;
struct ip6_pktopts *opt, *stickyopt;
- int priv, needcopy, uproto;
+ int priv, uproto;
{
struct cmsghdr *cm = 0;
if (control == NULL || opt == NULL)
return (EINVAL);
+ ip6_initpktopts(opt);
if (stickyopt) {
+ int error;
+
/*
* If stickyopt is provided, make a local copy of the options
* for this particular packet, then override them by ancillary
* objects.
- * XXX: need to gain a reference for the cached route of the
- * next hop in case of the overriding.
+ * XXX: copypktopts() does not copy the cached route to a next
+ * hop (if any). This is not very good in terms of efficiency,
+ * but we can allow this since this option should be rarely
+ * used.
*/
- *opt = *stickyopt;
- if (opt->ip6po_nextroute.ro_rt) {
- RT_LOCK(opt->ip6po_nextroute.ro_rt);
- RT_ADDREF(opt->ip6po_nextroute.ro_rt);
- RT_UNLOCK(opt->ip6po_nextroute.ro_rt);
- }
- } else
- ip6_initpktopts(opt);
- opt->needfree = needcopy;
+ if ((error = copypktopts(opt, stickyopt, M_NOWAIT)) != 0)
+ return (error);
+ }
/*
* XXX: Currently, we assume all the optional information is stored
@@ -3047,7 +3054,7 @@ ip6_setpktopts(control, opt, stickyopt, priv, needcopy, uproto)
continue;
error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm),
- cm->cmsg_len - CMSG_LEN(0), opt, priv, needcopy, 1, uproto);
+ cm->cmsg_len - CMSG_LEN(0), opt, priv, 0, 1, uproto);
if (error)
return (error);
}
@@ -3164,14 +3171,13 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto)
* XXX: the delay of the validation may confuse the
* application when it is used as a sticky option.
*/
- if (sticky) {
- if (opt->ip6po_pktinfo == NULL) {
- opt->ip6po_pktinfo = malloc(sizeof(*pktinfo),
- M_IP6OPT, M_WAITOK);
- }
- bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo));
- } else
- opt->ip6po_pktinfo = pktinfo;
+ if (opt->ip6po_pktinfo == NULL) {
+ opt->ip6po_pktinfo = malloc(sizeof(*pktinfo),
+ M_IP6OPT, M_NOWAIT);
+ if (opt->ip6po_pktinfo == NULL)
+ return (ENOBUFS);
+ }
+ bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo));
break;
}
@@ -3256,11 +3262,8 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto)
/* turn off the previous option, then set the new option. */
ip6_clearpktopts(opt, IPV6_NEXTHOP);
- if (sticky) {
- opt->ip6po_nexthop = malloc(*buf, M_IP6OPT, M_WAITOK);
- bcopy(buf, opt->ip6po_nexthop, *buf);
- } else
- opt->ip6po_nexthop = (struct sockaddr *)buf;
+ opt->ip6po_nexthop = malloc(*buf, M_IP6OPT, M_WAITOK);
+ bcopy(buf, opt->ip6po_nexthop, *buf);
break;
case IPV6_2292HOPOPTS:
@@ -3292,11 +3295,8 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto)
/* turn off the previous option, then set the new option. */
ip6_clearpktopts(opt, IPV6_HOPOPTS);
- if (sticky) {
- opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_WAITOK);
- bcopy(hbh, opt->ip6po_hbh, hbhlen);
- } else
- opt->ip6po_hbh = hbh;
+ opt->ip6po_hbh = malloc(hbhlen, M_IP6OPT, M_WAITOK);
+ bcopy(hbh, opt->ip6po_hbh, hbhlen);
break;
}
@@ -3357,11 +3357,8 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto)
/* turn off the previous option, then set the new option. */
ip6_clearpktopts(opt, optname);
- if (sticky) {
- *newdest = malloc(destlen, M_IP6OPT, M_WAITOK);
- bcopy(dest, *newdest, destlen);
- } else
- *newdest = dest;
+ *newdest = malloc(destlen, M_IP6OPT, M_WAITOK);
+ bcopy(dest, *newdest, destlen);
break;
}
@@ -3400,11 +3397,8 @@ ip6_setpktopt(optname, buf, len, opt, priv, sticky, cmsg, uproto)
/* turn off the previous option */
ip6_clearpktopts(opt, IPV6_RTHDR);
- if (sticky) {
- opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_WAITOK);
- bcopy(rth, opt->ip6po_rthdr, rthlen);
- } else
- opt->ip6po_rthdr = rth;
+ opt->ip6po_rthdr = malloc(rthlen, M_IP6OPT, M_WAITOK);
+ bcopy(rth, opt->ip6po_rthdr, rthlen);
break;
}
diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h
index 7f2a862..090dc31 100644
--- a/sys/netinet6/ip6_var.h
+++ b/sys/netinet6/ip6_var.h
@@ -173,8 +173,6 @@ struct ip6_pktopts {
#endif
#define IP6PO_DONTFRAG 0x04 /* disable fragmentation (IPV6_DONTFRAG) */
#define IP6PO_USECOA 0x08 /* use care of address */
-
- int needfree; /* members dynamically allocated */
};
/*
@@ -368,7 +366,7 @@ int ip6_ctloutput __P((struct socket *, struct sockopt *));
int ip6_raw_ctloutput __P((struct socket *, struct sockopt *));
void ip6_initpktopts __P((struct ip6_pktopts *));
int ip6_setpktopts __P((struct mbuf *, struct ip6_pktopts *,
- struct ip6_pktopts *, int, int, int));
+ struct ip6_pktopts *, int, int));
void ip6_clearpktopts __P((struct ip6_pktopts *, int));
struct ip6_pktopts *ip6_copypktopts __P((struct ip6_pktopts *, int));
int ip6_optlen __P((struct inpcb *));
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index d89d9f3..64304ac 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -346,7 +346,7 @@ rip6_output(m, va_alist)
dst = &dstsock->sin6_addr;
if (control) {
if ((error = ip6_setpktopts(control, &opt,
- in6p->in6p_outputopts, priv, 0, so->so_proto->pr_protocol))
+ in6p->in6p_outputopts, priv, so->so_proto->pr_protocol))
!= 0) {
goto bad;
}
diff --git a/sys/netinet6/udp6_output.c b/sys/netinet6/udp6_output.c
index a1a07be..933e3b3 100644
--- a/sys/netinet6/udp6_output.c
+++ b/sys/netinet6/udp6_output.c
@@ -141,7 +141,7 @@ udp6_output(in6p, m, addr6, control, td)
priv = 1;
if (control) {
if ((error = ip6_setpktopts(control, &opt,
- in6p->in6p_outputopts, priv, 0, IPPROTO_UDP)) != 0)
+ in6p->in6p_outputopts, priv, IPPROTO_UDP)) != 0)
goto release;
optp = &opt;
} else
OpenPOWER on IntegriCloud