Allow the old-style sockaddr_in6 for v6 addresses for which the
scope id is irrelevant. Makes netscape6 for Linux work again, which uses v4-mapped addresses to connect to v4 sites.
This commit is contained in:
parent
1c06d68731
commit
2c344fe7d9
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: linux_socket.c,v 1.33 2001/07/04 10:24:18 jdolecek Exp $ */
|
||||
/* $NetBSD: linux_socket.c,v 1.34 2001/09/08 14:19:09 fvdl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
|
||||
@ -104,7 +104,7 @@ int linux_to_bsd_tcp_sockopt __P((int));
|
||||
int linux_to_bsd_udp_sockopt __P((int));
|
||||
int linux_getifhwaddr __P((struct proc *, register_t *, u_int, void *));
|
||||
static int linux_sa_get __P((caddr_t *sgp, struct sockaddr **sap,
|
||||
const struct osockaddr *osa, int osalen));
|
||||
const struct osockaddr *osa, int *osalen));
|
||||
static int linux_sa_put __P((struct osockaddr *osa));
|
||||
|
||||
static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
|
||||
@ -254,24 +254,25 @@ linux_sys_sendto(p, v, retval)
|
||||
syscallarg(int) tolen;
|
||||
} */ *uap = v;
|
||||
struct sys_sendto_args bsa;
|
||||
int tolen;
|
||||
|
||||
SCARG(&bsa, s) = SCARG(uap, s);
|
||||
SCARG(&bsa, buf) = SCARG(uap, msg);
|
||||
SCARG(&bsa, len) = (size_t) SCARG(uap, len);
|
||||
SCARG(&bsa, flags) = SCARG(uap, flags);
|
||||
tolen = SCARG(uap, tolen);
|
||||
if (SCARG(uap, to)) {
|
||||
struct sockaddr *sa;
|
||||
int error;
|
||||
caddr_t sg = stackgap_init(p->p_emul);
|
||||
|
||||
if ((error = linux_sa_get(&sg, &sa, SCARG(uap, to),
|
||||
SCARG(uap, tolen))))
|
||||
if ((error = linux_sa_get(&sg, &sa, SCARG(uap, to), &tolen)))
|
||||
return (error);
|
||||
|
||||
SCARG(&bsa, to) = sa;
|
||||
} else
|
||||
SCARG(&bsa, to) = NULL;
|
||||
SCARG(&bsa, tolen) = SCARG(uap, tolen);
|
||||
SCARG(&bsa, tolen) = tolen;
|
||||
|
||||
return (sys_sendto(p, &bsa, retval));
|
||||
}
|
||||
@ -306,7 +307,7 @@ linux_sys_sendmsg(p, v, retval)
|
||||
return (ENOMEM);
|
||||
|
||||
error = linux_sa_get(&sg, &sa,
|
||||
(struct osockaddr *) msg.msg_name, msg.msg_namelen);
|
||||
(struct osockaddr *) msg.msg_name, &msg.msg_namelen);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
@ -869,14 +870,16 @@ linux_sys_connect(p, v, retval)
|
||||
struct sockaddr *sa;
|
||||
struct sys_connect_args bca;
|
||||
caddr_t sg = stackgap_init(p->p_emul);
|
||||
int namlen;
|
||||
|
||||
error = linux_sa_get(&sg, &sa, SCARG(uap, name), SCARG(uap, namelen));
|
||||
namlen = SCARG(uap, namelen);
|
||||
error = linux_sa_get(&sg, &sa, SCARG(uap, name), &namlen);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
SCARG(&bca, s) = SCARG(uap, s);
|
||||
SCARG(&bca, name) = sa;
|
||||
SCARG(&bca, namelen) = (unsigned int) SCARG(uap, namelen);
|
||||
SCARG(&bca, namelen) = (unsigned int) namlen;
|
||||
|
||||
error = sys_connect(p, &bca, retval);
|
||||
|
||||
@ -919,23 +922,23 @@ linux_sys_bind(p, v, retval)
|
||||
syscallarg(const struct osockaddr *) name;
|
||||
syscallarg(int) namelen;
|
||||
} */ *uap = v;
|
||||
int error;
|
||||
int error, namlen;
|
||||
struct sys_bind_args bsa;
|
||||
|
||||
namlen = SCARG(uap, namelen);
|
||||
SCARG(&bsa, s) = SCARG(uap, s);
|
||||
if (SCARG(uap, name)) {
|
||||
struct sockaddr *sa;
|
||||
caddr_t sg = stackgap_init(p->p_emul);
|
||||
|
||||
error = linux_sa_get(&sg, &sa, SCARG(uap, name),
|
||||
SCARG(uap, namelen));
|
||||
error = linux_sa_get(&sg, &sa, SCARG(uap, name), &namlen);
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
SCARG(&bsa, name) = sa;
|
||||
} else
|
||||
SCARG(&bsa, name) = NULL;
|
||||
SCARG(&bsa, namelen) = SCARG(uap, namelen);
|
||||
SCARG(&bsa, namelen) = namlen;
|
||||
|
||||
return (sys_bind(p, &bsa, retval));
|
||||
}
|
||||
@ -994,18 +997,37 @@ linux_sa_get(sgp, sap, osa, osalen)
|
||||
caddr_t *sgp;
|
||||
struct sockaddr **sap;
|
||||
const struct osockaddr *osa;
|
||||
int osalen;
|
||||
int *osalen;
|
||||
{
|
||||
int error=0, bdom;
|
||||
struct sockaddr *sa, *usa;
|
||||
struct osockaddr *kosa = (struct osockaddr *) &sa;
|
||||
int alloclen;
|
||||
#ifdef INET6
|
||||
int oldv6size;
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
|
||||
if (osalen < 0 || osalen > UCHAR_MAX || !osa)
|
||||
if (*osalen < 2 || *osalen > UCHAR_MAX || !osa)
|
||||
return (EINVAL);
|
||||
|
||||
kosa = (struct osockaddr *) malloc(osalen, M_TEMP, M_WAITOK);
|
||||
alloclen = *osalen;
|
||||
#ifdef INET6
|
||||
oldv6size = 0;
|
||||
/*
|
||||
* Check for old (pre-RFC2553) sockaddr_in6. We may accept it
|
||||
* if it's a v4-mapped address, so reserve the proper space
|
||||
* for it.
|
||||
*/
|
||||
if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
|
||||
alloclen = sizeof (struct sockaddr_in6);
|
||||
oldv6size = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((error = copyin(osa, (caddr_t) kosa, osalen)))
|
||||
kosa = (struct osockaddr *) malloc(alloclen, M_TEMP, M_WAITOK);
|
||||
|
||||
if ((error = copyin(osa, (caddr_t) kosa, *osalen)))
|
||||
goto out;
|
||||
|
||||
bdom = linux_to_bsd_domain(kosa->sa_family);
|
||||
@ -1019,36 +1041,50 @@ linux_sa_get(sgp, sap, osa, osalen)
|
||||
* Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
|
||||
* which lacks the scope id compared with RFC2553 one. If we detect
|
||||
* the situation, reject the address and write a message to system log.
|
||||
*
|
||||
* Still accept addresses for which the scope id is not used.
|
||||
*/
|
||||
if (bdom == AF_INET6 && osalen < sizeof(struct sockaddr_in6)) {
|
||||
struct proc *p = curproc; /* XXX */
|
||||
int uid = p->p_cred && p->p_ucred ?
|
||||
p->p_ucred->cr_uid : -1;
|
||||
if (oldv6size && bdom == AF_INET6) {
|
||||
sin6 = (struct sockaddr_in6 *)kosa;
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
|
||||
(!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
|
||||
!IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
|
||||
!IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
|
||||
!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
|
||||
!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
|
||||
sin6->sin6_scope_id = 0;
|
||||
} else {
|
||||
struct proc *p = curproc; /* XXX */
|
||||
int uid = p->p_cred && p->p_ucred ?
|
||||
p->p_ucred->cr_uid : -1;
|
||||
|
||||
log(LOG_DEBUG,
|
||||
"pid %d (%s), uid %d: obsolete pre-RFC2553 sockaddr_in6 rejected",
|
||||
p->p_pid, p->p_comm, uid);
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
log(LOG_DEBUG,
|
||||
"pid %d (%s), uid %d: obsolete pre-RFC2553 "
|
||||
"sockaddr_in6 rejected",
|
||||
p->p_pid, p->p_comm, uid);
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sa = (struct sockaddr *) kosa;
|
||||
sa->sa_family = bdom;
|
||||
sa->sa_len = osalen;
|
||||
sa->sa_len = alloclen;
|
||||
|
||||
usa = (struct sockaddr *) stackgap_alloc(sgp, osalen);
|
||||
usa = (struct sockaddr *) stackgap_alloc(sgp, alloclen);
|
||||
if (!usa) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((error = copyout(sa, usa, osalen)))
|
||||
if ((error = copyout(sa, usa, alloclen)))
|
||||
goto out;
|
||||
|
||||
*sap = usa;
|
||||
|
||||
out:
|
||||
*osalen = alloclen;
|
||||
free(kosa, M_TEMP);
|
||||
return (error);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user