MFC
This commit is contained in:
commit
dbab0763f9
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/largeSMP/; revision=223140
@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
|
||||
/*
|
||||
* Routines to expand arguments to commands. We have to deal with
|
||||
@ -1400,6 +1401,36 @@ get_wc(const char **p)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* See if a character matches a character class, starting at the first colon
|
||||
* of "[:class:]".
|
||||
* If a valid character class is recognized, a pointer to the next character
|
||||
* after the final closing bracket is stored into *end, otherwise a null
|
||||
* pointer is stored into *end.
|
||||
*/
|
||||
static int
|
||||
match_charclass(const char *p, wchar_t chr, const char **end)
|
||||
{
|
||||
char name[20];
|
||||
const char *nameend;
|
||||
wctype_t cclass;
|
||||
|
||||
*end = NULL;
|
||||
p++;
|
||||
nameend = strstr(p, ":]");
|
||||
if (nameend == NULL || nameend - p >= sizeof(name) || nameend == p)
|
||||
return 0;
|
||||
memcpy(name, p, nameend - p);
|
||||
name[nameend - p] = '\0';
|
||||
*end = nameend + 2;
|
||||
cclass = wctype(name);
|
||||
/* An unknown class matches nothing but is valid nevertheless. */
|
||||
if (cclass == 0)
|
||||
return 0;
|
||||
return iswctype(chr, cclass);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns true if the pattern matches the string.
|
||||
*/
|
||||
@ -1407,7 +1438,7 @@ get_wc(const char **p)
|
||||
int
|
||||
patmatch(const char *pattern, const char *string, int squoted)
|
||||
{
|
||||
const char *p, *q;
|
||||
const char *p, *q, *end;
|
||||
char c;
|
||||
wchar_t wc, wc2;
|
||||
|
||||
@ -1495,6 +1526,11 @@ patmatch(const char *pattern, const char *string, int squoted)
|
||||
do {
|
||||
if (c == CTLQUOTEMARK)
|
||||
continue;
|
||||
if (c == '[' && *p == ':') {
|
||||
found |= match_charclass(p, chr, &end);
|
||||
if (end != NULL)
|
||||
p = end;
|
||||
}
|
||||
if (c == CTLESC)
|
||||
c = *p++;
|
||||
if (localeisutf8 && c & 0x80) {
|
||||
|
12
bin/sh/sh.1
12
bin/sh/sh.1
@ -32,7 +32,7 @@
|
||||
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 12, 2011
|
||||
.Dd June 15, 2011
|
||||
.Dt SH 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -1648,6 +1648,15 @@ matches a
|
||||
rather than introducing a character class.
|
||||
A character class matches any of the characters between the square brackets.
|
||||
A range of characters may be specified using a minus sign.
|
||||
A named class of characters (see
|
||||
.Xr wctype 3 )
|
||||
may be specified by surrounding the name with
|
||||
.Ql \&[:
|
||||
and
|
||||
.Ql :\&] .
|
||||
For example,
|
||||
.Ql \&[\&[:alpha:\&]\&]
|
||||
is a shell pattern that matches a single letter.
|
||||
The character class may be complemented by making an exclamation point
|
||||
.Pq Ql !\&
|
||||
the first character of the character class.
|
||||
@ -2572,6 +2581,7 @@ will return the argument.
|
||||
.Xr execve 2 ,
|
||||
.Xr getrlimit 2 ,
|
||||
.Xr umask 2 ,
|
||||
.Xr wctype 3 ,
|
||||
.Xr editrc 5
|
||||
.Sh HISTORY
|
||||
A
|
||||
|
@ -46,7 +46,7 @@ case "$daily_scrub_zfs_enable" in
|
||||
esac
|
||||
|
||||
# determine how many days shall be between scrubs
|
||||
eval _pool_threshold=\${daily_scrub_zfs_$(echo "${pool}"|tr -s "-" "_"|tr -s "." "_"|tr -s ":" "_")_threshold}
|
||||
eval _pool_threshold=\${daily_scrub_zfs_$(echo "${pool}"|tr ".:-" "_")_threshold}
|
||||
if [ -z "${_pool_threshold}" ];then
|
||||
_pool_threshold=${daily_scrub_zfs_default_threshold}
|
||||
fi
|
||||
|
@ -599,11 +599,11 @@ sysconf(name)
|
||||
|
||||
#ifdef _SC_CPUSET_SIZE
|
||||
case _SC_CPUSET_SIZE:
|
||||
len = sizeof(lvalue);
|
||||
if (sysctlbyname("kern.sched.cpusetsize", &lvalue, &len, NULL,
|
||||
len = sizeof(value);
|
||||
if (sysctlbyname("kern.sched.cpusetsize", &value, &len, NULL,
|
||||
0) == -1)
|
||||
return (-1);
|
||||
return (lvalue);
|
||||
return ((long)value);
|
||||
#endif
|
||||
|
||||
default:
|
||||
|
@ -141,7 +141,7 @@ in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
|
||||
int
|
||||
sctp_getaddrlen(sa_family_t family)
|
||||
{
|
||||
int error, sd;
|
||||
int ret, sd;
|
||||
socklen_t siz;
|
||||
struct sctp_assoc_value av;
|
||||
|
||||
@ -151,13 +151,15 @@ sctp_getaddrlen(sa_family_t family)
|
||||
sd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
|
||||
#elif defined(AF_INET6)
|
||||
sd = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);
|
||||
#else
|
||||
sd = -1;
|
||||
#endif
|
||||
if (sd == -1) {
|
||||
return (-1);
|
||||
}
|
||||
error = getsockopt(sd, IPPROTO_SCTP, SCTP_GET_ADDR_LEN, &av, &siz);
|
||||
ret = getsockopt(sd, IPPROTO_SCTP, SCTP_GET_ADDR_LEN, &av, &siz);
|
||||
close(sd);
|
||||
if (error == 0) {
|
||||
if (ret == 0) {
|
||||
return ((int)av.assoc_value);
|
||||
} else {
|
||||
return (-1);
|
||||
@ -402,6 +404,9 @@ sctp_opt_info(int sd, sctp_assoc_t id, int opt, void *arg, socklen_t * size)
|
||||
case SCTP_TIMEOUTS:
|
||||
((struct sctp_timeouts *)arg)->stimo_assoc_id = id;
|
||||
break;
|
||||
case SCTP_EVENT:
|
||||
((struct sctp_event *)arg)->se_assoc_id = id;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -919,32 +924,259 @@ sctp_recvmsg(int s,
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_SCTP_PEELOFF_SOCKOPT)
|
||||
#include <netinet/sctp_peeloff.h>
|
||||
|
||||
int
|
||||
sctp_peeloff(int sd, sctp_assoc_t assoc_id)
|
||||
ssize_t
|
||||
sctp_recvv(int sd,
|
||||
const struct iovec *iov,
|
||||
int iovlen,
|
||||
struct sockaddr *from,
|
||||
socklen_t * fromlen,
|
||||
void *info,
|
||||
socklen_t * infolen,
|
||||
unsigned int *infotype,
|
||||
int *flags)
|
||||
{
|
||||
struct sctp_peeloff_opt peeloff;
|
||||
int result;
|
||||
socklen_t optlen;
|
||||
char ctlbuf[SCTP_CONTROL_VEC_SIZE_RCV];
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
ssize_t n;
|
||||
struct sctp_rcvinfo *rcvinfo;
|
||||
struct sctp_nxtinfo *nxtinfo;
|
||||
|
||||
/* set in the socket option params */
|
||||
memset(&peeloff, 0, sizeof(peeloff));
|
||||
peeloff.s = sd;
|
||||
peeloff.assoc_id = assoc_id;
|
||||
optlen = sizeof(peeloff);
|
||||
result = getsockopt(sd, IPPROTO_SCTP, SCTP_PEELOFF, (void *)&peeloff, &optlen);
|
||||
|
||||
if (result < 0) {
|
||||
return (-1);
|
||||
} else {
|
||||
return (peeloff.new_sd);
|
||||
if (infotype) {
|
||||
*infotype = SCTP_RECVV_NOINFO;
|
||||
}
|
||||
msg.msg_name = from;
|
||||
if (fromlen == NULL) {
|
||||
msg.msg_namelen = 0;
|
||||
} else {
|
||||
msg.msg_namelen = *fromlen;
|
||||
}
|
||||
msg.msg_iov = (struct iovec *)iov;
|
||||
msg.msg_iovlen = iovlen;
|
||||
msg.msg_control = ctlbuf;
|
||||
msg.msg_controllen = sizeof(ctlbuf);
|
||||
errno = 0;
|
||||
n = recvmsg(sd, &msg, *flags);
|
||||
*flags = msg.msg_flags;
|
||||
if ((n > 0) &&
|
||||
(msg.msg_controllen > 0) &&
|
||||
(infotype != NULL) &&
|
||||
(infolen != NULL) &&
|
||||
(*infolen > 0)) {
|
||||
rcvinfo = NULL;
|
||||
nxtinfo = NULL;
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != IPPROTO_SCTP) {
|
||||
continue;
|
||||
}
|
||||
if (cmsg->cmsg_type == SCTP_RCVINFO) {
|
||||
rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
|
||||
}
|
||||
if (cmsg->cmsg_type == SCTP_NXTINFO) {
|
||||
nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmsg);
|
||||
}
|
||||
if (rcvinfo && nxtinfo) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rcvinfo) {
|
||||
if (nxtinfo) {
|
||||
if (*infolen >= sizeof(struct sctp_recvv_rn)) {
|
||||
struct sctp_recvv_rn *rn_info;
|
||||
|
||||
rn_info = (struct sctp_recvv_rn *)info;
|
||||
rn_info->recvv_rcvinfo = *rcvinfo;
|
||||
rn_info->recvv_nxtinfo = *nxtinfo;
|
||||
*infolen = (socklen_t) sizeof(struct sctp_recvv_rn);
|
||||
*infotype = SCTP_RECVV_RN;
|
||||
}
|
||||
} else {
|
||||
if (*infolen >= sizeof(struct sctp_rcvinfo)) {
|
||||
memcpy(info, rcvinfo, sizeof(struct sctp_rcvinfo));
|
||||
*infolen = (socklen_t) sizeof(struct sctp_rcvinfo);
|
||||
*infotype = SCTP_RECVV_RCVINFO;
|
||||
}
|
||||
}
|
||||
} else if (nxtinfo) {
|
||||
if (*infolen >= sizeof(struct sctp_rcvinfo)) {
|
||||
memcpy(info, nxtinfo, sizeof(struct sctp_nxtinfo));
|
||||
*infolen = (socklen_t) sizeof(struct sctp_nxtinfo);
|
||||
*infotype = SCTP_RECVV_NXTINFO;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
ssize_t
|
||||
sctp_sendv(int sd,
|
||||
const struct iovec *iov, int iovcnt,
|
||||
struct sockaddr *addrs, int addrcnt,
|
||||
void *info, socklen_t infolen, unsigned int infotype,
|
||||
int flags)
|
||||
{
|
||||
ssize_t ret;
|
||||
int i;
|
||||
size_t addr_len;
|
||||
struct sctp_sendv_spa *spa_info;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
char *cmsgbuf;
|
||||
struct sockaddr *addr;
|
||||
struct sockaddr_in *addr_in;
|
||||
struct sockaddr_in6 *addr_in6;
|
||||
|
||||
if ((addrcnt < 0) || (iovcnt < 0)) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
cmsgbuf = malloc(CMSG_SPACE(sizeof(struct sctp_sndinfo)) +
|
||||
CMSG_SPACE(sizeof(struct sctp_prinfo)) +
|
||||
CMSG_SPACE(sizeof(struct sctp_authinfo)) +
|
||||
addrcnt * CMSG_SPACE(sizeof(struct in6_addr)));
|
||||
if (cmsgbuf == NULL) {
|
||||
errno = ENOBUFS;
|
||||
return (-1);
|
||||
}
|
||||
msg.msg_control = cmsgbuf;
|
||||
msg.msg_controllen = 0;
|
||||
cmsg = (struct cmsghdr *)cmsgbuf;
|
||||
switch (infotype) {
|
||||
case SCTP_SENDV_SNDINFO:
|
||||
if (infolen < sizeof(struct sctp_sndinfo)) {
|
||||
free(cmsgbuf);
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
cmsg->cmsg_level = IPPROTO_SCTP;
|
||||
cmsg->cmsg_type = SCTP_SNDINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
|
||||
memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_sndinfo));
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
|
||||
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
|
||||
break;
|
||||
case SCTP_SENDV_PRINFO:
|
||||
if (infolen < sizeof(struct sctp_prinfo)) {
|
||||
free(cmsgbuf);
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
cmsg->cmsg_level = IPPROTO_SCTP;
|
||||
cmsg->cmsg_type = SCTP_PRINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
|
||||
memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_prinfo));
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
|
||||
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
|
||||
break;
|
||||
case SCTP_SENDV_AUTHINFO:
|
||||
if (infolen < sizeof(struct sctp_authinfo)) {
|
||||
free(cmsgbuf);
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
cmsg->cmsg_level = IPPROTO_SCTP;
|
||||
cmsg->cmsg_type = SCTP_AUTHINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
|
||||
memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_authinfo));
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
|
||||
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
|
||||
break;
|
||||
case SCTP_SENDV_SPA:
|
||||
if (infolen < sizeof(struct sctp_sendv_spa)) {
|
||||
free(cmsgbuf);
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
spa_info = (struct sctp_sendv_spa *)info;
|
||||
if (spa_info->sendv_flags & SCTP_SEND_SNDINFO_VALID) {
|
||||
cmsg->cmsg_level = IPPROTO_SCTP;
|
||||
cmsg->cmsg_type = SCTP_SNDINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
|
||||
memcpy(CMSG_DATA(cmsg), &spa_info->sendv_sndinfo, sizeof(struct sctp_sndinfo));
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
|
||||
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
|
||||
}
|
||||
if (spa_info->sendv_flags & SCTP_SEND_PRINFO_VALID) {
|
||||
cmsg->cmsg_level = IPPROTO_SCTP;
|
||||
cmsg->cmsg_type = SCTP_PRINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
|
||||
memcpy(CMSG_DATA(cmsg), &spa_info->sendv_prinfo, sizeof(struct sctp_prinfo));
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
|
||||
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
|
||||
}
|
||||
if (spa_info->sendv_flags & SCTP_SEND_AUTHINFO_VALID) {
|
||||
cmsg->cmsg_level = IPPROTO_SCTP;
|
||||
cmsg->cmsg_type = SCTP_AUTHINFO;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
|
||||
memcpy(CMSG_DATA(cmsg), &spa_info->sendv_authinfo, sizeof(struct sctp_authinfo));
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
|
||||
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
free(cmsgbuf);
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
addr = addrs;
|
||||
if (addrcnt == 1) {
|
||||
msg.msg_name = addr;
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
msg.msg_namelen = sizeof(struct sockaddr_in);
|
||||
break;
|
||||
case AF_INET6:
|
||||
msg.msg_namelen = sizeof(struct sockaddr_in6);
|
||||
break;
|
||||
default:
|
||||
free(cmsgbuf);
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
} else {
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
for (i = 0; i < addrcnt; i++) {
|
||||
switch (addr->sa_family) {
|
||||
case AF_INET:
|
||||
addr_len = sizeof(struct sockaddr_in);
|
||||
addr_in = (struct sockaddr_in *)addr;
|
||||
cmsg->cmsg_level = IPPROTO_SCTP;
|
||||
cmsg->cmsg_type = SCTP_DSTADDRV4;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
|
||||
memcpy(CMSG_DATA(cmsg), &addr_in->sin_addr, sizeof(struct in_addr));
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
|
||||
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr)));
|
||||
break;
|
||||
case AF_INET6:
|
||||
addr_len = sizeof(struct sockaddr_in6);
|
||||
addr_in6 = (struct sockaddr_in6 *)addr;
|
||||
cmsg->cmsg_level = IPPROTO_SCTP;
|
||||
cmsg->cmsg_type = SCTP_DSTADDRV6;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_addr));
|
||||
memcpy(CMSG_DATA(cmsg), &addr_in6->sin6_addr, sizeof(struct in6_addr));
|
||||
msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_addr));
|
||||
cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr)));
|
||||
break;
|
||||
default:
|
||||
free(cmsgbuf);
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
addr = (struct sockaddr *)((caddr_t)addr + addr_len);
|
||||
}
|
||||
}
|
||||
if (msg.msg_controllen == 0) {
|
||||
msg.msg_control = NULL;
|
||||
}
|
||||
msg.msg_iov = (struct iovec *)iov;
|
||||
msg.msg_iovlen = iovcnt;
|
||||
msg.msg_flags = 0;
|
||||
ret = sendmsg(sd, &msg, flags);
|
||||
free(cmsgbuf);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(SYS_sctp_peeloff) && !defined(HAVE_SCTP_PEELOFF_SOCKOPT)
|
||||
|
||||
|
@ -15,7 +15,7 @@ NO_PIC=
|
||||
INCS= stand.h
|
||||
MAN= libstand.3
|
||||
|
||||
WARNS?= 0
|
||||
WARNS?= 2
|
||||
|
||||
CFLAGS+= -ffreestanding -Wformat
|
||||
CFLAGS+= -I${.CURDIR}
|
||||
|
@ -100,7 +100,7 @@ sendrecv(struct iodesc *d,
|
||||
cc, ssize);
|
||||
|
||||
tleft = tmo;
|
||||
tmo <<= 1;
|
||||
tmo += MINTMO;
|
||||
if (tmo > MAXTMO)
|
||||
tmo = MAXTMO;
|
||||
|
||||
|
@ -60,12 +60,21 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "tftp.h"
|
||||
|
||||
struct tftp_handle;
|
||||
|
||||
static int tftp_open(const char *path, struct open_file *f);
|
||||
static int tftp_close(struct open_file *f);
|
||||
static void tftp_parse_oack(struct tftp_handle *h, char *buf, size_t len);
|
||||
static int tftp_read(struct open_file *f, void *buf, size_t size, size_t *resid);
|
||||
static int tftp_write(struct open_file *f, void *buf, size_t size, size_t *resid);
|
||||
static off_t tftp_seek(struct open_file *f, off_t offset, int where);
|
||||
static int tftp_set_blksize(struct tftp_handle *h, const char *str);
|
||||
static int tftp_stat(struct open_file *f, struct stat *sb);
|
||||
static ssize_t sendrecv_tftp(struct tftp_handle *h,
|
||||
ssize_t (*sproc)(struct iodesc *, void *, size_t),
|
||||
void *sbuf, size_t ssize,
|
||||
ssize_t (*rproc)(struct tftp_handle *h, void *, ssize_t, time_t, unsigned short *),
|
||||
void *rbuf, size_t rsize, unsigned short *rtype);
|
||||
|
||||
struct fs_ops tftp_fsops = {
|
||||
"tftp",
|
||||
@ -81,8 +90,20 @@ struct fs_ops tftp_fsops = {
|
||||
extern struct in_addr servip;
|
||||
|
||||
static int tftpport = 2000;
|
||||
static int is_open = 0;
|
||||
|
||||
#define RSPACE 520 /* max data packet, rounded up */
|
||||
/*
|
||||
* The legacy TFTP_BLKSIZE value was 512.
|
||||
* TFTP_REQUESTED_BLKSIZE of 1428 is (Ethernet MTU, less the TFTP, UDP and
|
||||
* IP header lengths).
|
||||
*/
|
||||
#define TFTP_REQUESTED_BLKSIZE 1428
|
||||
|
||||
/*
|
||||
* Choose a blksize big enough so we can test with Ethernet
|
||||
* Jumbo frames in the future.
|
||||
*/
|
||||
#define TFTP_MAX_BLKSIZE 9008
|
||||
|
||||
struct tftp_handle {
|
||||
struct iodesc *iodesc;
|
||||
@ -91,10 +112,12 @@ struct tftp_handle {
|
||||
int validsize;
|
||||
int off;
|
||||
char *path; /* saved for re-requests */
|
||||
unsigned int tftp_blksize;
|
||||
unsigned long tftp_tsize;
|
||||
struct {
|
||||
u_char header[HEADER_SIZE];
|
||||
struct tftphdr t;
|
||||
u_char space[RSPACE];
|
||||
u_char space[TFTP_MAX_BLKSIZE];
|
||||
} __packed __aligned(4) lastdata;
|
||||
};
|
||||
|
||||
@ -110,8 +133,10 @@ static const int tftperrors[8] = {
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
recvtftp(struct iodesc *d, void *pkt, ssize_t len, time_t tleft)
|
||||
recvtftp(struct tftp_handle *h, void *pkt, ssize_t len, time_t tleft,
|
||||
unsigned short *rtype)
|
||||
{
|
||||
struct iodesc *d = h->iodesc;
|
||||
struct tftphdr *t;
|
||||
|
||||
errno = 0;
|
||||
@ -122,6 +147,7 @@ recvtftp(struct iodesc *d, void *pkt, ssize_t len, time_t tleft)
|
||||
return (-1);
|
||||
|
||||
t = (struct tftphdr *) pkt;
|
||||
*rtype = ntohs(t->th_opcode);
|
||||
switch (ntohs(t->th_opcode)) {
|
||||
case DATA: {
|
||||
int got;
|
||||
@ -154,6 +180,18 @@ recvtftp(struct iodesc *d, void *pkt, ssize_t len, time_t tleft)
|
||||
errno = tftperrors[ntohs(t->th_code)];
|
||||
}
|
||||
return (-1);
|
||||
case OACK: {
|
||||
struct udphdr *uh;
|
||||
int tftp_oack_len = len - sizeof(t->th_opcode);
|
||||
tftp_parse_oack(h, t->th_u.tu_stuff, tftp_oack_len);
|
||||
/*
|
||||
* Remember which port this OACK came from,
|
||||
* because we need to send the ACK back to it.
|
||||
*/
|
||||
uh = (struct udphdr *) pkt - 1;
|
||||
d->destport = uh->uh_sport;
|
||||
return (0);
|
||||
}
|
||||
default:
|
||||
#ifdef TFTP_DEBUG
|
||||
printf("tftp type %d not handled\n", ntohs(t->th_opcode));
|
||||
@ -175,14 +213,35 @@ tftp_makereq(struct tftp_handle *h)
|
||||
int l;
|
||||
ssize_t res;
|
||||
struct tftphdr *t;
|
||||
char *tftp_blksize = NULL;
|
||||
int blksize_l;
|
||||
unsigned short rtype = 0;
|
||||
|
||||
/*
|
||||
* Allow overriding default TFTP block size by setting
|
||||
* a tftp.blksize environment variable.
|
||||
*/
|
||||
if ((tftp_blksize = getenv("tftp.blksize")) != NULL) {
|
||||
tftp_set_blksize(h, tftp_blksize);
|
||||
}
|
||||
|
||||
wbuf.t.th_opcode = htons((u_short) RRQ);
|
||||
wtail = wbuf.t.th_stuff;
|
||||
l = strlen(h->path);
|
||||
if (l > FNAME_SIZE)
|
||||
return (ENAMETOOLONG);
|
||||
bcopy(h->path, wtail, l + 1);
|
||||
wtail += l + 1;
|
||||
bcopy("octet", wtail, 6);
|
||||
wtail += 6;
|
||||
bcopy("blksize", wtail, 8);
|
||||
wtail += 8;
|
||||
blksize_l = sprintf(wtail, "%d", h->tftp_blksize);
|
||||
wtail += blksize_l + 1;
|
||||
bcopy("tsize", wtail, 6);
|
||||
wtail += 6;
|
||||
bcopy("0", wtail, 2);
|
||||
wtail += 2;
|
||||
|
||||
t = &h->lastdata.t;
|
||||
|
||||
@ -191,18 +250,33 @@ tftp_makereq(struct tftp_handle *h)
|
||||
h->iodesc->destport = htons(IPPORT_TFTP);
|
||||
h->iodesc->xid = 1; /* expected block */
|
||||
|
||||
res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
|
||||
recvtftp, t, sizeof(*t) + RSPACE);
|
||||
res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
|
||||
&recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype);
|
||||
|
||||
if (res == -1)
|
||||
return (errno);
|
||||
if (rtype == OACK) {
|
||||
wbuf.t.th_opcode = htons((u_short)ACK);
|
||||
wtail = (char *) &wbuf.t.th_block;
|
||||
wbuf.t.th_block = htons(0);
|
||||
wtail += 2;
|
||||
rtype = 0;
|
||||
res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
|
||||
&recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype);
|
||||
}
|
||||
|
||||
switch (rtype) {
|
||||
case DATA: {
|
||||
h->currblock = 1;
|
||||
h->validsize = res;
|
||||
h->islastblock = 0;
|
||||
if (res < h->tftp_blksize)
|
||||
h->islastblock = 1; /* very short file */
|
||||
return (0);
|
||||
}
|
||||
case ERROR:
|
||||
default:
|
||||
return (errno);
|
||||
}
|
||||
|
||||
h->currblock = 1;
|
||||
h->validsize = res;
|
||||
h->islastblock = 0;
|
||||
if (res < SEGSIZE)
|
||||
h->islastblock = 1; /* very short file */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* ack block, expect next */
|
||||
@ -216,7 +290,7 @@ tftp_getnextblock(struct tftp_handle *h)
|
||||
char *wtail;
|
||||
int res;
|
||||
struct tftphdr *t;
|
||||
|
||||
unsigned short rtype = 0;
|
||||
wbuf.t.th_opcode = htons((u_short) ACK);
|
||||
wtail = (char *) &wbuf.t.th_block;
|
||||
wbuf.t.th_block = htons((u_short) h->currblock);
|
||||
@ -226,16 +300,23 @@ tftp_getnextblock(struct tftp_handle *h)
|
||||
|
||||
h->iodesc->xid = h->currblock + 1; /* expected block */
|
||||
|
||||
res = sendrecv(h->iodesc, sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
|
||||
recvtftp, t, sizeof(*t) + RSPACE);
|
||||
res = sendrecv_tftp(h, &sendudp, &wbuf.t, wtail - (char *) &wbuf.t,
|
||||
&recvtftp, t, sizeof(*t) + h->tftp_blksize, &rtype);
|
||||
|
||||
if (res == -1) /* 0 is OK! */
|
||||
return (errno);
|
||||
|
||||
h->currblock++;
|
||||
h->validsize = res;
|
||||
if (res < SEGSIZE)
|
||||
if (res < h->tftp_blksize)
|
||||
h->islastblock = 1; /* EOF */
|
||||
|
||||
if (h->islastblock == 1) {
|
||||
/* Send an ACK for the last block */
|
||||
wbuf.t.th_block = htons((u_short) h->currblock);
|
||||
sendudp(h->iodesc, &wbuf.t, wtail - (char *)&wbuf.t);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -251,10 +332,15 @@ tftp_open(const char *path, struct open_file *f)
|
||||
return (EINVAL);
|
||||
#endif
|
||||
|
||||
if (is_open)
|
||||
return (EBUSY);
|
||||
|
||||
tftpfile = (struct tftp_handle *) malloc(sizeof(*tftpfile));
|
||||
if (!tftpfile)
|
||||
return (ENOMEM);
|
||||
|
||||
memset(tftpfile, 0, sizeof(*tftpfile));
|
||||
tftpfile->tftp_blksize = TFTP_REQUESTED_BLKSIZE;
|
||||
tftpfile->iodesc = io = socktodesc(*(int *) (f->f_devdata));
|
||||
if (io == NULL)
|
||||
return (EINVAL);
|
||||
@ -275,6 +361,7 @@ tftp_open(const char *path, struct open_file *f)
|
||||
return (res);
|
||||
}
|
||||
f->f_fsdata = (void *) tftpfile;
|
||||
is_open = 1;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -292,7 +379,7 @@ tftp_read(struct open_file *f, void *addr, size_t size,
|
||||
if (!(tc++ % 16))
|
||||
twiddle();
|
||||
|
||||
needblock = tftpfile->off / SEGSIZE + 1;
|
||||
needblock = tftpfile->off / tftpfile->tftp_blksize + 1;
|
||||
|
||||
if (tftpfile->currblock > needblock) /* seek backwards */
|
||||
tftp_makereq(tftpfile); /* no error check, it worked
|
||||
@ -315,7 +402,7 @@ tftp_read(struct open_file *f, void *addr, size_t size,
|
||||
if (tftpfile->currblock == needblock) {
|
||||
int offinblock, inbuffer;
|
||||
|
||||
offinblock = tftpfile->off % SEGSIZE;
|
||||
offinblock = tftpfile->off % tftpfile->tftp_blksize;
|
||||
|
||||
inbuffer = tftpfile->validsize - offinblock;
|
||||
if (inbuffer < 0) {
|
||||
@ -361,18 +448,19 @@ tftp_close(struct open_file *f)
|
||||
free(tftpfile->path);
|
||||
free(tftpfile);
|
||||
}
|
||||
is_open = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
tftp_write(struct open_file *f __unused, void *start __unused, size_t size __unused,
|
||||
size_t *resid /* out */ __unused)
|
||||
size_t *resid __unused /* out */)
|
||||
{
|
||||
return (EROFS);
|
||||
}
|
||||
|
||||
static int
|
||||
tftp_stat(struct open_file *f, struct stat *sb)
|
||||
tftp_stat(struct open_file *f, struct stat *sb)
|
||||
{
|
||||
struct tftp_handle *tftpfile;
|
||||
tftpfile = (struct tftp_handle *) f->f_fsdata;
|
||||
@ -404,3 +492,166 @@ tftp_seek(struct open_file *f, off_t offset, int where)
|
||||
}
|
||||
return (tftpfile->off);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
sendrecv_tftp(struct tftp_handle *h,
|
||||
ssize_t (*sproc)(struct iodesc *, void *, size_t),
|
||||
void *sbuf, size_t ssize,
|
||||
ssize_t (*rproc)(struct tftp_handle *, void *, ssize_t, time_t, unsigned short *),
|
||||
void *rbuf, size_t rsize, unsigned short *rtype)
|
||||
{
|
||||
struct iodesc *d = h->iodesc;
|
||||
ssize_t cc;
|
||||
time_t t, t1, tleft;
|
||||
|
||||
#ifdef TFTP_DEBUG
|
||||
if (debug)
|
||||
printf("sendrecv: called\n");
|
||||
#endif
|
||||
|
||||
tleft = MINTMO;
|
||||
t = t1 = getsecs();
|
||||
for (;;) {
|
||||
if ((getsecs() - t) > MAXTMO) {
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cc = (*sproc)(d, sbuf, ssize);
|
||||
if (cc != -1 && cc < ssize)
|
||||
panic("sendrecv: short write! (%zd < %zu)",
|
||||
cc, ssize);
|
||||
|
||||
if (cc == -1) {
|
||||
/* Error on transmit; wait before retrying */
|
||||
while ((getsecs() - t1) < tleft);
|
||||
continue;
|
||||
}
|
||||
|
||||
recvnext:
|
||||
/* Try to get a packet and process it. */
|
||||
cc = (*rproc)(h, rbuf, rsize, tleft, rtype);
|
||||
/* Return on data, EOF or real error. */
|
||||
if (cc != -1 || errno != 0)
|
||||
return (cc);
|
||||
if ((getsecs() - t1) < tleft) {
|
||||
goto recvnext;
|
||||
}
|
||||
|
||||
/* Timed out or didn't get the packet we're waiting for */
|
||||
tleft += MINTMO;
|
||||
if (tleft > (2 * MINTMO)) {
|
||||
tleft = (2 * MINTMO);
|
||||
}
|
||||
t1 = getsecs();
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
tftp_set_blksize(struct tftp_handle *h, const char *str)
|
||||
{
|
||||
char *endptr;
|
||||
int new_blksize;
|
||||
int ret = 0;
|
||||
|
||||
if (h == NULL || str == NULL)
|
||||
return (ret);
|
||||
|
||||
new_blksize =
|
||||
(unsigned int)strtol(str, &endptr, 0);
|
||||
|
||||
/*
|
||||
* Only accept blksize value if it is numeric.
|
||||
* RFC2348 specifies that acceptable valuesare 8-65464
|
||||
* 8-65464 . Let's choose a limit less than MAXRSPACE
|
||||
*/
|
||||
if (*endptr == '\0' && new_blksize >= 8
|
||||
&& new_blksize <= TFTP_MAX_BLKSIZE) {
|
||||
h->tftp_blksize = new_blksize;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* In RFC2347, the TFTP Option Acknowledgement package (OACK)
|
||||
* is used to acknowledge a client's option negotiation request.
|
||||
* The format of an OACK packet is:
|
||||
* +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
|
||||
* | opc | opt1 | 0 | value1 | 0 | optN | 0 | valueN | 0 |
|
||||
* +-------+---~~---+---+---~~---+---+---~~---+---+---~~---+---+
|
||||
*
|
||||
* opc
|
||||
* The opcode field contains a 6, for Option Acknowledgment.
|
||||
*
|
||||
* opt1
|
||||
* The first option acknowledgment, copied from the original
|
||||
* request.
|
||||
*
|
||||
* value1
|
||||
* The acknowledged value associated with the first option. If
|
||||
* and how this value may differ from the original request is
|
||||
* detailed in the specification for the option.
|
||||
*
|
||||
* optN, valueN
|
||||
* The final option/value acknowledgment pair.
|
||||
*/
|
||||
static void
|
||||
tftp_parse_oack(struct tftp_handle *h, char *buf, size_t len)
|
||||
{
|
||||
/*
|
||||
* We parse the OACK strings into an array
|
||||
* of name-value pairs.
|
||||
*
|
||||
*/
|
||||
char *tftp_options[128] = { 0 };
|
||||
char *val = buf;
|
||||
int i = 0;
|
||||
int option_idx = 0;
|
||||
int blksize_is_set = 0;
|
||||
int tsize = 0;
|
||||
|
||||
|
||||
while ( option_idx < 128 && i < len ) {
|
||||
if (buf[i] == '\0') {
|
||||
if (&buf[i] > val) {
|
||||
tftp_options[option_idx] = val;
|
||||
val = &buf[i] + 1;
|
||||
++option_idx;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse individual TFTP options.
|
||||
* * "blksize" is specified in RFC2348.
|
||||
* * "tsize" is specified in RFC2349.
|
||||
*/
|
||||
for (i = 0; i < option_idx; i += 2) {
|
||||
if (strcasecmp(tftp_options[i], "blksize") == 0) {
|
||||
if (i + 1 < option_idx) {
|
||||
blksize_is_set =
|
||||
tftp_set_blksize(h, tftp_options[i + 1]);
|
||||
}
|
||||
} else if (strcasecmp(tftp_options[i], "tsize") == 0) {
|
||||
if (i + 1 < option_idx) {
|
||||
tsize = strtol(tftp_options[i + 1], (char **)NULL, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!blksize_is_set) {
|
||||
/*
|
||||
* If TFTP blksize was not set, try defaulting
|
||||
* to the legacy TFTP blksize of 512
|
||||
*/
|
||||
h->tftp_blksize = 512;
|
||||
}
|
||||
|
||||
#ifdef TFTP_DEBUG
|
||||
printf("tftp_blksize: %u\n", h->tftp_blksize);
|
||||
printf("tftp_tsize: %lu\n", h->tftp_tsize);
|
||||
#endif
|
||||
}
|
||||
|
@ -253,8 +253,9 @@ was introduced in
|
||||
support for the TFTP Blocksize Option (RFC2348) and the blksize2 option
|
||||
was introduced in
|
||||
.Fx 7.4 .
|
||||
.Sh BUGS
|
||||
.Sh NOTES
|
||||
Files larger than 33488896 octets (65535 blocks) cannot be transferred
|
||||
without client and server supporting blocksize negotiation (RFC2348).
|
||||
without client and server supporting the the TFTP blocksize option (RFC2348),
|
||||
or the non-standard TFTP rollover option.
|
||||
.Pp
|
||||
Many tftp clients will not transfer files over 16744448 octets (32767 blocks).
|
||||
|
@ -110,8 +110,8 @@ reldoc:
|
||||
system: packagesystem
|
||||
# Install system
|
||||
-mkdir ${.OBJDIR}/release
|
||||
cd ${WORLDDIR} && ${IMAKE} installkernel installworld distribution DESTDIR=${.OBJDIR}/release
|
||||
-rm ${.OBJDIR}/release/boot/kernel/*.symbols
|
||||
cd ${WORLDDIR} && ${IMAKE} installkernel installworld distribution \
|
||||
DESTDIR=${.OBJDIR}/release WITHOUT_RESCUE=1 WITHOUT_KERNEL_SYMBOLS=1
|
||||
# Copy distfiles
|
||||
mkdir ${.OBJDIR}/release/usr/freebsd-dist
|
||||
cp ${.OBJDIR}/*.txz ${.OBJDIR}/MANIFEST \
|
||||
@ -135,8 +135,9 @@ bootonly: packagesystem
|
||||
WITHOUT_BIND_DNSSEC=1 WITHOUT_BIND_ETC=1 WITHOUT_BIND_MTREE=1 \
|
||||
WITHOUT_BIND_NAMED=1 WITHOUT_GAMES=1 WITHOUT_GROFF=1 \
|
||||
WITHOUT_INSTALLLIB=1 WITHOUT_LIB32=1 WITHOUT_MAIL=1 \
|
||||
WITHOUT_NCP=1 WITHOUT_TOOLCHAIN=1 WITHOUT_RESCUE=1 WITHOUT_DICT=1
|
||||
-rm ${.OBJDIR}/bootonly/boot/kernel/*.symbols
|
||||
WITHOUT_NCP=1 WITHOUT_TOOLCHAIN=1 WITHOUT_PROFILE=1 \
|
||||
WITHOUT_INSTALLIB=1 WITHOUT_RESCUE=1 WITHOUT_DICT=1 \
|
||||
WITHOUT_KERNEL_SYMBOLS=1
|
||||
# Copy manifest only (no distfiles) to get checksums
|
||||
mkdir ${.OBJDIR}/bootonly/usr/freebsd-dist
|
||||
cp ${.OBJDIR}/MANIFEST ${.OBJDIR}/bootonly/usr/freebsd-dist
|
||||
|
@ -10,8 +10,5 @@ start
|
||||
\ Tests for password -- executes autoboot first if a password was defined
|
||||
check-password
|
||||
|
||||
\ Load in the boot menu
|
||||
include /boot/beastie.4th
|
||||
\ Unless set otherwise, autoboot is automatic at this point
|
||||
|
||||
\ Start the boot menu
|
||||
beastie-start
|
||||
|
@ -108,7 +108,8 @@ ${KERNEL_KO}.tramp: ${KERNEL_KO} $S/$M/$M/inckern.S $S/$M/$M/elf_trampoline.c
|
||||
gzip -9 ${KERNEL_KO}.tmp
|
||||
eval $$(stat -s ${KERNEL_KO}.tmp.gz) && \
|
||||
echo "#define KERNCOMPSIZE $$st_size" >>opt_kernname.h
|
||||
${CC} -O2 -DKZIP -I. -I$S -c $S/kern/inflate.c -o inflate-tramp.o
|
||||
${CC} -O2 -ffreestanding -DKZIP -I. -I$S -c $S/kern/inflate.c -o \
|
||||
inflate-tramp.o
|
||||
${CC} -O -nostdlib -I. -I$S -Xlinker -T -Xlinker ldscript.$M.tramp \
|
||||
-DKZIP tmphack.S $S/$M/$M/elf_trampoline.c inflate-tramp.o \
|
||||
$S/$M/$M/inckern.S ${FILES_CPU_FUNC} -o ${KERNEL_KO}.gz.tramp
|
||||
|
@ -4146,7 +4146,10 @@ hdac_attach(device_t dev)
|
||||
uint16_t vendor;
|
||||
uint8_t v;
|
||||
|
||||
device_printf(dev, "HDA Driver Revision: %s\n", HDA_DRV_TEST_REV);
|
||||
HDA_BOOTVERBOSE(
|
||||
device_printf(dev, "HDA Driver Revision: %s\n",
|
||||
HDA_DRV_TEST_REV);
|
||||
);
|
||||
|
||||
model = (uint32_t)pci_get_device(dev) << 16;
|
||||
model |= (uint32_t)pci_get_vendor(dev) & 0x0000ffff;
|
||||
|
@ -91,7 +91,7 @@ struct sctp_paramhdr {
|
||||
#define SCTP_PEER_ADDR_PARAMS 0x0000000a
|
||||
#define SCTP_DEFAULT_SEND_PARAM 0x0000000b
|
||||
/* ancillary data/notification interest options */
|
||||
#define SCTP_EVENTS 0x0000000c
|
||||
#define SCTP_EVENTS 0x0000000c /* deprecated */
|
||||
/* Without this applied we will give V4 and V6 addresses on a V6 socket */
|
||||
#define SCTP_I_WANT_MAPPED_V4_ADDR 0x0000000d
|
||||
#define SCTP_MAXSEG 0x0000000e
|
||||
@ -114,6 +114,10 @@ struct sctp_paramhdr {
|
||||
#define SCTP_EXPLICIT_EOR 0x0000001b
|
||||
#define SCTP_REUSE_PORT 0x0000001c /* rw */
|
||||
#define SCTP_AUTH_DEACTIVATE_KEY 0x0000001d
|
||||
#define SCTP_EVENT 0x0000001e
|
||||
#define SCTP_RECVRCVINFO 0x0000001f
|
||||
#define SCTP_RECVNXTINFO 0x00000020
|
||||
#define SCTP_DEFAULT_SNDINFO 0x00000021
|
||||
|
||||
/*
|
||||
* read-only options
|
||||
@ -490,7 +494,7 @@ struct sctp_error_unrecognized_chunk {
|
||||
/*
|
||||
* PCB Features (in sctp_features bitmask)
|
||||
*/
|
||||
#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x00000002
|
||||
#define SCTP_PCB_FLAGS_EXT_RCVINFO 0x00000002 /* deprecated */
|
||||
#define SCTP_PCB_FLAGS_DONOT_HEARTBEAT 0x00000004
|
||||
#define SCTP_PCB_FLAGS_FRAG_INTERLEAVE 0x00000008
|
||||
#define SCTP_PCB_FLAGS_INTERLEAVE_STRMS 0x00000010
|
||||
@ -500,7 +504,7 @@ struct sctp_error_unrecognized_chunk {
|
||||
/* socket options */
|
||||
#define SCTP_PCB_FLAGS_NODELAY 0x00000100
|
||||
#define SCTP_PCB_FLAGS_AUTOCLOSE 0x00000200
|
||||
#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x00000400
|
||||
#define SCTP_PCB_FLAGS_RECVDATAIOEVNT 0x00000400 /* deprecated */
|
||||
#define SCTP_PCB_FLAGS_RECVASSOCEVNT 0x00000800
|
||||
#define SCTP_PCB_FLAGS_RECVPADDREVNT 0x00001000
|
||||
#define SCTP_PCB_FLAGS_RECVPEERERR 0x00002000
|
||||
@ -516,6 +520,9 @@ struct sctp_error_unrecognized_chunk {
|
||||
#define SCTP_PCB_FLAGS_MULTIPLE_ASCONFS 0x01000000
|
||||
#define SCTP_PCB_FLAGS_PORTREUSE 0x02000000
|
||||
#define SCTP_PCB_FLAGS_DRYEVNT 0x04000000
|
||||
#define SCTP_PCB_FLAGS_RECVRCVINFO 0x08000000
|
||||
#define SCTP_PCB_FLAGS_RECVNXTINFO 0x10000000
|
||||
|
||||
/*-
|
||||
* mobility_features parameters (by micchie).Note
|
||||
* these features are applied against the
|
||||
|
@ -1866,7 +1866,7 @@ sctp_notify_authentication(struct sctp_tcb *stcb, uint32_t indication,
|
||||
/* If the socket is gone we are out of here */
|
||||
return;
|
||||
}
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_AUTHEVNT))
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_AUTHEVNT))
|
||||
/* event not enabled */
|
||||
return;
|
||||
|
||||
|
@ -201,48 +201,110 @@ sctp_build_readq_entry_chk(struct sctp_tcb *stcb,
|
||||
|
||||
|
||||
struct mbuf *
|
||||
sctp_build_ctl_nchunk(struct sctp_inpcb *inp,
|
||||
struct sctp_sndrcvinfo *sinfo)
|
||||
sctp_build_ctl_nchunk(struct sctp_inpcb *inp, struct sctp_sndrcvinfo *sinfo)
|
||||
{
|
||||
struct sctp_extrcvinfo *seinfo;
|
||||
struct sctp_sndrcvinfo *outinfo;
|
||||
struct sctp_rcvinfo *rcvinfo;
|
||||
struct sctp_nxtinfo *nxtinfo;
|
||||
struct cmsghdr *cmh;
|
||||
struct mbuf *ret;
|
||||
int len;
|
||||
int use_extended = 0;
|
||||
int use_extended;
|
||||
int provide_nxt;
|
||||
|
||||
if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
|
||||
/* user does not want the sndrcv ctl */
|
||||
if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) &&
|
||||
sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
|
||||
sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) {
|
||||
/* user does not want any ancillary data */
|
||||
return (NULL);
|
||||
}
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
|
||||
use_extended = 1;
|
||||
len = CMSG_LEN(sizeof(struct sctp_extrcvinfo));
|
||||
len = 0;
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
|
||||
len += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
|
||||
}
|
||||
seinfo = (struct sctp_extrcvinfo *)sinfo;
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO) &&
|
||||
(seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_AVAIL)) {
|
||||
provide_nxt = 1;
|
||||
len += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
|
||||
} else {
|
||||
len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
|
||||
provide_nxt = 0;
|
||||
}
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
|
||||
use_extended = 1;
|
||||
len += CMSG_SPACE(sizeof(struct sctp_extrcvinfo));
|
||||
} else {
|
||||
use_extended = 0;
|
||||
len += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
|
||||
}
|
||||
} else {
|
||||
use_extended = 0;
|
||||
}
|
||||
|
||||
|
||||
ret = sctp_get_mbuf_for_msg(len,
|
||||
0, M_DONTWAIT, 1, MT_DATA);
|
||||
|
||||
ret = sctp_get_mbuf_for_msg(len, 0, M_DONTWAIT, 1, MT_DATA);
|
||||
if (ret == NULL) {
|
||||
/* No space */
|
||||
return (ret);
|
||||
}
|
||||
/* We need a CMSG header followed by the struct */
|
||||
SCTP_BUF_LEN(ret) = 0;
|
||||
|
||||
/* We need a CMSG header followed by the struct */
|
||||
cmh = mtod(ret, struct cmsghdr *);
|
||||
outinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmh);
|
||||
cmh->cmsg_level = IPPROTO_SCTP;
|
||||
if (use_extended) {
|
||||
cmh->cmsg_type = SCTP_EXTRCV;
|
||||
cmh->cmsg_len = len;
|
||||
memcpy(outinfo, sinfo, len);
|
||||
} else {
|
||||
cmh->cmsg_type = SCTP_SNDRCV;
|
||||
cmh->cmsg_len = len;
|
||||
*outinfo = *sinfo;
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO)) {
|
||||
cmh->cmsg_level = IPPROTO_SCTP;
|
||||
cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_rcvinfo));
|
||||
cmh->cmsg_type = SCTP_RCVINFO;
|
||||
rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmh);
|
||||
rcvinfo->rcv_sid = sinfo->sinfo_stream;
|
||||
rcvinfo->rcv_ssn = sinfo->sinfo_ssn;
|
||||
rcvinfo->rcv_flags = sinfo->sinfo_flags;
|
||||
rcvinfo->rcv_ppid = sinfo->sinfo_ppid;
|
||||
rcvinfo->rcv_tsn = sinfo->sinfo_tsn;
|
||||
rcvinfo->rcv_cumtsn = sinfo->sinfo_cumtsn;
|
||||
rcvinfo->rcv_context = sinfo->sinfo_context;
|
||||
rcvinfo->rcv_assoc_id = sinfo->sinfo_assoc_id;
|
||||
cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_rcvinfo)));
|
||||
SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_rcvinfo));
|
||||
}
|
||||
if (provide_nxt) {
|
||||
cmh->cmsg_level = IPPROTO_SCTP;
|
||||
cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_nxtinfo));
|
||||
cmh->cmsg_type = SCTP_NXTINFO;
|
||||
nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmh);
|
||||
nxtinfo->nxt_sid = seinfo->sreinfo_next_stream;
|
||||
nxtinfo->nxt_flags = 0;
|
||||
if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_UNORDERED) {
|
||||
nxtinfo->nxt_flags |= SCTP_UNORDERED;
|
||||
}
|
||||
if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_IS_NOTIFICATION) {
|
||||
nxtinfo->nxt_flags |= SCTP_NOTIFICATION;
|
||||
}
|
||||
if (seinfo->sreinfo_next_flags & SCTP_NEXT_MSG_ISCOMPLETE) {
|
||||
nxtinfo->nxt_flags |= SCTP_COMPLETE;
|
||||
}
|
||||
nxtinfo->nxt_ppid = seinfo->sreinfo_next_ppid;
|
||||
nxtinfo->nxt_length = seinfo->sreinfo_next_length;
|
||||
nxtinfo->nxt_assoc_id = seinfo->sreinfo_next_aid;
|
||||
cmh = (struct cmsghdr *)((caddr_t)cmh + CMSG_SPACE(sizeof(struct sctp_nxtinfo)));
|
||||
SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_nxtinfo));
|
||||
}
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT)) {
|
||||
cmh->cmsg_level = IPPROTO_SCTP;
|
||||
outinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmh);
|
||||
if (use_extended) {
|
||||
cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_extrcvinfo));
|
||||
cmh->cmsg_type = SCTP_EXTRCV;
|
||||
memcpy(outinfo, sinfo, sizeof(struct sctp_extrcvinfo));
|
||||
SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_extrcvinfo));
|
||||
} else {
|
||||
cmh->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
|
||||
cmh->cmsg_type = SCTP_SNDRCV;
|
||||
*outinfo = *sinfo;
|
||||
SCTP_BUF_LEN(ret) += CMSG_SPACE(sizeof(struct sctp_sndrcvinfo));
|
||||
}
|
||||
}
|
||||
SCTP_BUF_LEN(ret) = cmh->cmsg_len;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
@ -3355,54 +3355,338 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
|
||||
}
|
||||
|
||||
static int
|
||||
sctp_find_cmsg(int c_type, void *data, struct mbuf *control, int cpsize)
|
||||
sctp_find_cmsg(int c_type, void *data, struct mbuf *control, size_t cpsize)
|
||||
{
|
||||
struct cmsghdr cmh;
|
||||
int tlen, at;
|
||||
int tlen, at, found;
|
||||
struct sctp_sndinfo sndinfo;
|
||||
struct sctp_prinfo prinfo;
|
||||
struct sctp_authinfo authinfo;
|
||||
|
||||
tlen = SCTP_BUF_LEN(control);
|
||||
at = 0;
|
||||
found = 0;
|
||||
/*
|
||||
* Independent of how many mbufs, find the c_type inside the control
|
||||
* structure and copy out the data.
|
||||
*/
|
||||
while (at < tlen) {
|
||||
if ((tlen - at) < (int)CMSG_ALIGN(sizeof(cmh))) {
|
||||
/* not enough room for one more we are done. */
|
||||
return (0);
|
||||
/* There is not enough room for one more. */
|
||||
return (found);
|
||||
}
|
||||
m_copydata(control, at, sizeof(cmh), (caddr_t)&cmh);
|
||||
if (cmh.cmsg_len < CMSG_ALIGN(sizeof(struct cmsghdr))) {
|
||||
/* We dont't have a complete CMSG header. */
|
||||
return (found);
|
||||
}
|
||||
if (((int)cmh.cmsg_len + at) > tlen) {
|
||||
/*
|
||||
* this is real messed up since there is not enough
|
||||
* data here to cover the cmsg header. We are done.
|
||||
*/
|
||||
return (0);
|
||||
/* We don't have the complete CMSG. */
|
||||
return (found);
|
||||
}
|
||||
if ((cmh.cmsg_level == IPPROTO_SCTP) &&
|
||||
(c_type == cmh.cmsg_type)) {
|
||||
/* found the one we want, copy it out */
|
||||
at += CMSG_ALIGN(sizeof(struct cmsghdr));
|
||||
if ((int)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < cpsize) {
|
||||
/*
|
||||
* space of cmsg_len after header not big
|
||||
* enough
|
||||
*/
|
||||
return (0);
|
||||
((c_type == cmh.cmsg_type) ||
|
||||
((c_type == SCTP_SNDRCV) &&
|
||||
((cmh.cmsg_type == SCTP_SNDINFO) ||
|
||||
(cmh.cmsg_type == SCTP_PRINFO) ||
|
||||
(cmh.cmsg_type == SCTP_AUTHINFO))))) {
|
||||
if (c_type == cmh.cmsg_type) {
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < cpsize) {
|
||||
return (found);
|
||||
}
|
||||
/* It is exactly what we want. Copy it out. */
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), cpsize, (caddr_t)data);
|
||||
return (1);
|
||||
} else {
|
||||
struct sctp_sndrcvinfo *sndrcvinfo;
|
||||
|
||||
sndrcvinfo = (struct sctp_sndrcvinfo *)data;
|
||||
if (found == 0) {
|
||||
if (cpsize < sizeof(struct sctp_sndrcvinfo)) {
|
||||
return (found);
|
||||
}
|
||||
memset(sndrcvinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
}
|
||||
switch (cmh.cmsg_type) {
|
||||
case SCTP_SNDINFO:
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < sizeof(struct sctp_sndinfo)) {
|
||||
return (found);
|
||||
}
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), sizeof(struct sctp_sndinfo), (caddr_t)&sndinfo);
|
||||
sndrcvinfo->sinfo_stream = sndinfo.snd_sid;
|
||||
sndrcvinfo->sinfo_flags = sndinfo.snd_flags;
|
||||
sndrcvinfo->sinfo_ppid = sndinfo.snd_ppid;
|
||||
sndrcvinfo->sinfo_context = sndinfo.snd_context;
|
||||
sndrcvinfo->sinfo_assoc_id = sndinfo.snd_assoc_id;
|
||||
break;
|
||||
case SCTP_PRINFO:
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < sizeof(struct sctp_prinfo)) {
|
||||
return (found);
|
||||
}
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), sizeof(struct sctp_prinfo), (caddr_t)&prinfo);
|
||||
sndrcvinfo->sinfo_timetolive = prinfo.pr_value;
|
||||
sndrcvinfo->sinfo_flags |= prinfo.pr_policy;
|
||||
break;
|
||||
case SCTP_AUTHINFO:
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < sizeof(struct sctp_authinfo)) {
|
||||
return (found);
|
||||
}
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), sizeof(struct sctp_authinfo), (caddr_t)&authinfo);
|
||||
sndrcvinfo->sinfo_keynumber_valid = 1;
|
||||
sndrcvinfo->sinfo_keynumber = authinfo.auth_keyid;
|
||||
break;
|
||||
default:
|
||||
return (found);
|
||||
}
|
||||
found = 1;
|
||||
}
|
||||
m_copydata(control, at, cpsize, data);
|
||||
}
|
||||
at += CMSG_ALIGN(cmh.cmsg_len);
|
||||
}
|
||||
return (found);
|
||||
}
|
||||
|
||||
static int
|
||||
sctp_process_cmsgs_for_init(struct sctp_tcb *stcb, struct mbuf *control, int *error)
|
||||
{
|
||||
struct cmsghdr cmh;
|
||||
int tlen, at;
|
||||
struct sctp_initmsg initmsg;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
#endif
|
||||
|
||||
tlen = SCTP_BUF_LEN(control);
|
||||
at = 0;
|
||||
while (at < tlen) {
|
||||
if ((tlen - at) < (int)CMSG_ALIGN(sizeof(cmh))) {
|
||||
/* There is not enough room for one more. */
|
||||
*error = EINVAL;
|
||||
return (1);
|
||||
} else {
|
||||
at += CMSG_ALIGN(cmh.cmsg_len);
|
||||
if (cmh.cmsg_len == 0) {
|
||||
}
|
||||
m_copydata(control, at, sizeof(cmh), (caddr_t)&cmh);
|
||||
if (cmh.cmsg_len < CMSG_ALIGN(sizeof(struct cmsghdr))) {
|
||||
/* We dont't have a complete CMSG header. */
|
||||
*error = EINVAL;
|
||||
return (1);
|
||||
}
|
||||
if (((int)cmh.cmsg_len + at) > tlen) {
|
||||
/* We don't have the complete CMSG. */
|
||||
*error = EINVAL;
|
||||
return (1);
|
||||
}
|
||||
if (cmh.cmsg_level == IPPROTO_SCTP) {
|
||||
switch (cmh.cmsg_type) {
|
||||
case SCTP_INIT:
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < sizeof(struct sctp_initmsg)) {
|
||||
*error = EINVAL;
|
||||
return (1);
|
||||
}
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), sizeof(struct sctp_initmsg), (caddr_t)&initmsg);
|
||||
if (initmsg.sinit_max_attempts)
|
||||
stcb->asoc.max_init_times = initmsg.sinit_max_attempts;
|
||||
if (initmsg.sinit_num_ostreams)
|
||||
stcb->asoc.pre_open_streams = initmsg.sinit_num_ostreams;
|
||||
if (initmsg.sinit_max_instreams)
|
||||
stcb->asoc.max_inbound_streams = initmsg.sinit_max_instreams;
|
||||
if (initmsg.sinit_max_init_timeo)
|
||||
stcb->asoc.initial_init_rto_max = initmsg.sinit_max_init_timeo;
|
||||
if (stcb->asoc.streamoutcnt < stcb->asoc.pre_open_streams) {
|
||||
struct sctp_stream_out *tmp_str;
|
||||
unsigned int i;
|
||||
|
||||
/* Default is NOT correct */
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Ok, default:%d pre_open:%d\n",
|
||||
stcb->asoc.streamoutcnt, stcb->asoc.pre_open_streams);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
SCTP_MALLOC(tmp_str,
|
||||
struct sctp_stream_out *,
|
||||
(stcb->asoc.pre_open_streams * sizeof(struct sctp_stream_out)),
|
||||
SCTP_M_STRMO);
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
if (tmp_str != NULL) {
|
||||
SCTP_FREE(stcb->asoc.strmout, SCTP_M_STRMO);
|
||||
stcb->asoc.strmout = tmp_str;
|
||||
stcb->asoc.strm_realoutsize = stcb->asoc.streamoutcnt = stcb->asoc.pre_open_streams;
|
||||
} else {
|
||||
stcb->asoc.pre_open_streams = stcb->asoc.streamoutcnt;
|
||||
}
|
||||
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
|
||||
stcb->asoc.strmout[i].next_sequence_sent = 0;
|
||||
TAILQ_INIT(&stcb->asoc.strmout[i].outqueue);
|
||||
stcb->asoc.strmout[i].stream_no = i;
|
||||
stcb->asoc.strmout[i].last_msg_incomplete = 0;
|
||||
stcb->asoc.ss_functions.sctp_ss_init_stream(&stcb->asoc.strmout[i], NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef INET
|
||||
case SCTP_DSTADDRV4:
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < sizeof(struct in_addr)) {
|
||||
*error = EINVAL;
|
||||
return (1);
|
||||
}
|
||||
memset(&sin, 0, sizeof(struct sockaddr_in));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_port = stcb->rport;
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), sizeof(struct in_addr), (caddr_t)&sin.sin_addr);
|
||||
if ((sin.sin_addr.s_addr == INADDR_ANY) ||
|
||||
(sin.sin_addr.s_addr == INADDR_BROADCAST) ||
|
||||
IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
|
||||
*error = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
|
||||
*error = ENOBUFS;
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case SCTP_DSTADDRV6:
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < sizeof(struct in6_addr)) {
|
||||
*error = EINVAL;
|
||||
return (1);
|
||||
}
|
||||
memset(&sin6, 0, sizeof(struct sockaddr_in6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_port = stcb->rport;
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), sizeof(struct in6_addr), (caddr_t)&sin6.sin6_addr);
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr) ||
|
||||
IN6_IS_ADDR_MULTICAST(&sin6.sin6_addr)) {
|
||||
*error = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
#ifdef INET
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin, &sin6);
|
||||
if ((sin.sin_addr.s_addr == INADDR_ANY) ||
|
||||
(sin.sin_addr.s_addr == INADDR_BROADCAST) ||
|
||||
IN_MULTICAST(ntohl(sin.sin_addr.s_addr))) {
|
||||
*error = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
|
||||
*error = ENOBUFS;
|
||||
return (1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (sctp_add_remote_addr(stcb, (struct sockaddr *)&sin6, SCTP_DONOT_SETSCOPE, SCTP_ADDR_IS_CONFIRMED)) {
|
||||
*error = ENOBUFS;
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
at += CMSG_ALIGN(cmh.cmsg_len);
|
||||
}
|
||||
/* not found */
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct sctp_tcb *
|
||||
sctp_findassociation_cmsgs(struct sctp_inpcb **inp_p,
|
||||
in_port_t port,
|
||||
struct mbuf *control,
|
||||
struct sctp_nets **net_p,
|
||||
int *error)
|
||||
{
|
||||
struct cmsghdr cmh;
|
||||
int tlen, at;
|
||||
struct sctp_tcb *stcb;
|
||||
struct sockaddr *addr;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin;
|
||||
|
||||
#endif
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
#endif
|
||||
|
||||
tlen = SCTP_BUF_LEN(control);
|
||||
at = 0;
|
||||
while (at < tlen) {
|
||||
if ((tlen - at) < (int)CMSG_ALIGN(sizeof(cmh))) {
|
||||
/* There is not enough room for one more. */
|
||||
*error = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
m_copydata(control, at, sizeof(cmh), (caddr_t)&cmh);
|
||||
if (cmh.cmsg_len < CMSG_ALIGN(sizeof(struct cmsghdr))) {
|
||||
/* We dont't have a complete CMSG header. */
|
||||
*error = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (((int)cmh.cmsg_len + at) > tlen) {
|
||||
/* We don't have the complete CMSG. */
|
||||
*error = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (cmh.cmsg_level == IPPROTO_SCTP) {
|
||||
switch (cmh.cmsg_type) {
|
||||
#ifdef INET
|
||||
case SCTP_DSTADDRV4:
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < sizeof(struct in_addr)) {
|
||||
*error = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
memset(&sin, 0, sizeof(struct sockaddr_in));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_len = sizeof(struct sockaddr_in);
|
||||
sin.sin_port = port;
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), sizeof(struct in_addr), (caddr_t)&sin.sin_addr);
|
||||
addr = (struct sockaddr *)&sin;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case SCTP_DSTADDRV6:
|
||||
if ((size_t)(cmh.cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr))) < sizeof(struct in6_addr)) {
|
||||
*error = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
memset(&sin6, 0, sizeof(struct sockaddr_in6));
|
||||
sin6.sin6_family = AF_INET6;
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_port = port;
|
||||
m_copydata(control, at + CMSG_ALIGN(sizeof(struct cmsghdr)), sizeof(struct in6_addr), (caddr_t)&sin6.sin6_addr);
|
||||
#ifdef INET
|
||||
if (IN6_IS_ADDR_V4MAPPED(&sin6.sin6_addr)) {
|
||||
in6_sin6_2_sin(&sin, &sin6);
|
||||
addr = (struct sockaddr *)&sin;
|
||||
} else
|
||||
#endif
|
||||
addr = (struct sockaddr *)&sin6;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
addr = NULL;
|
||||
break;
|
||||
}
|
||||
if (addr) {
|
||||
stcb = sctp_findassociation_ep_addr(inp_p, addr, net_p, NULL, NULL);
|
||||
if (stcb != NULL) {
|
||||
return (stcb);
|
||||
}
|
||||
}
|
||||
}
|
||||
at += CMSG_ALIGN(cmh.cmsg_len);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static struct mbuf *
|
||||
sctp_add_cookie(struct sctp_inpcb *inp, struct mbuf *init, int init_offset,
|
||||
struct mbuf *initack, int initack_offset, struct sctp_state_cookie *stc_in, uint8_t ** signature)
|
||||
@ -5989,19 +6273,26 @@ sctp_msg_append(struct sctp_tcb *stcb,
|
||||
sp->some_taken = 0;
|
||||
sp->data = m;
|
||||
sp->tail_mbuf = NULL;
|
||||
sp->length = 0;
|
||||
at = m;
|
||||
sctp_set_prsctp_policy(sp);
|
||||
/*
|
||||
* We could in theory (for sendall) sifa the length in, but we would
|
||||
* still have to hunt through the chain since we need to setup the
|
||||
* tail_mbuf
|
||||
*/
|
||||
while (at) {
|
||||
sp->length = 0;
|
||||
for (at = m; at; at = SCTP_BUF_NEXT(at)) {
|
||||
if (SCTP_BUF_NEXT(at) == NULL)
|
||||
sp->tail_mbuf = at;
|
||||
sp->length += SCTP_BUF_LEN(at);
|
||||
at = SCTP_BUF_NEXT(at);
|
||||
}
|
||||
if (srcv->sinfo_keynumber_valid) {
|
||||
sp->auth_keyid = srcv->sinfo_keynumber;
|
||||
} else {
|
||||
sp->auth_keyid = stcb->asoc.authinfo.active_keyid;
|
||||
}
|
||||
if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
|
||||
sctp_auth_key_acquire(stcb, sp->auth_keyid);
|
||||
sp->holds_key_ref = 1;
|
||||
}
|
||||
SCTP_TCB_SEND_LOCK(stcb);
|
||||
sctp_snd_sb_alloc(stcb, sp->length);
|
||||
@ -6478,7 +6769,9 @@ sctp_sendall(struct sctp_inpcb *inp, struct uio *uio, struct mbuf *m,
|
||||
memset(ca, 0, sizeof(struct sctp_copy_all));
|
||||
|
||||
ca->inp = inp;
|
||||
memcpy(&ca->sndrcv, srcv, sizeof(struct sctp_nonpad_sndrcvinfo));
|
||||
if (srcv) {
|
||||
memcpy(&ca->sndrcv, srcv, sizeof(struct sctp_nonpad_sndrcvinfo));
|
||||
}
|
||||
/*
|
||||
* take off the sendall flag, it would be bad if we failed to do
|
||||
* this :-0
|
||||
@ -12229,9 +12522,13 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
|
||||
*error = 0;
|
||||
goto skip_copy;
|
||||
}
|
||||
sp->auth_keyid = stcb->asoc.authinfo.active_keyid;
|
||||
if (srcv->sinfo_keynumber_valid) {
|
||||
sp->auth_keyid = srcv->sinfo_keynumber;
|
||||
} else {
|
||||
sp->auth_keyid = stcb->asoc.authinfo.active_keyid;
|
||||
}
|
||||
if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
|
||||
sctp_auth_key_acquire(stcb, stcb->asoc.authinfo.active_keyid);
|
||||
sctp_auth_key_acquire(stcb, sp->auth_keyid);
|
||||
sp->holds_key_ref = 1;
|
||||
}
|
||||
*error = sctp_copy_one(sp, uio, resv_in_first);
|
||||
@ -12263,8 +12560,8 @@ sctp_sosend(struct socket *so,
|
||||
struct thread *p
|
||||
)
|
||||
{
|
||||
int error, use_rcvinfo = 0;
|
||||
struct sctp_sndrcvinfo srcv;
|
||||
int error, use_sndinfo = 0;
|
||||
struct sctp_sndrcvinfo sndrcvninfo;
|
||||
struct sockaddr *addr_to_use;
|
||||
|
||||
#if defined(INET) && defined(INET6)
|
||||
@ -12274,10 +12571,10 @@ sctp_sosend(struct socket *so,
|
||||
|
||||
if (control) {
|
||||
/* process cmsg snd/rcv info (maybe a assoc-id) */
|
||||
if (sctp_find_cmsg(SCTP_SNDRCV, (void *)&srcv, control,
|
||||
sizeof(srcv))) {
|
||||
if (sctp_find_cmsg(SCTP_SNDRCV, (void *)&sndrcvninfo, control,
|
||||
sizeof(sndrcvninfo))) {
|
||||
/* got one */
|
||||
use_rcvinfo = 1;
|
||||
use_sndinfo = 1;
|
||||
}
|
||||
}
|
||||
addr_to_use = addr;
|
||||
@ -12295,7 +12592,7 @@ sctp_sosend(struct socket *so,
|
||||
error = sctp_lower_sosend(so, addr_to_use, uio, top,
|
||||
control,
|
||||
flags,
|
||||
use_rcvinfo ? &srcv : NULL
|
||||
use_sndinfo ? &sndrcvninfo : NULL
|
||||
,p
|
||||
);
|
||||
return (error);
|
||||
@ -12500,6 +12797,9 @@ sctp_lower_sosend(struct socket *so,
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
/* With the lock applied look again */
|
||||
stcb = sctp_findassociation_ep_addr(&t_inp, addr, &net, NULL, NULL);
|
||||
if ((stcb == NULL) && (control != NULL) && (port > 0)) {
|
||||
stcb = sctp_findassociation_cmsgs(&t_inp, port, control, &net, &error);
|
||||
}
|
||||
if (stcb == NULL) {
|
||||
SCTP_INP_WLOCK(inp);
|
||||
SCTP_INP_DECR_REF(inp);
|
||||
@ -12507,6 +12807,9 @@ sctp_lower_sosend(struct socket *so,
|
||||
} else {
|
||||
hold_tcblock = 1;
|
||||
}
|
||||
if (error) {
|
||||
goto out_unlocked;
|
||||
}
|
||||
if (t_inp != inp) {
|
||||
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOTCONN);
|
||||
error = ENOTCONN;
|
||||
@ -12555,6 +12858,7 @@ sctp_lower_sosend(struct socket *so,
|
||||
/* Error is setup for us in the call */
|
||||
goto out_unlocked;
|
||||
}
|
||||
hold_tcblock = 1;
|
||||
if (create_lock_applied) {
|
||||
SCTP_ASOC_CREATE_UNLOCK(inp);
|
||||
create_lock_applied = 0;
|
||||
@ -12574,84 +12878,13 @@ sctp_lower_sosend(struct socket *so,
|
||||
sctp_initialize_auth_params(inp, stcb);
|
||||
|
||||
if (control) {
|
||||
/*
|
||||
* see if a init structure exists in cmsg
|
||||
* headers
|
||||
*/
|
||||
struct sctp_initmsg initm;
|
||||
int i;
|
||||
|
||||
if (sctp_find_cmsg(SCTP_INIT, (void *)&initm, control,
|
||||
sizeof(initm))) {
|
||||
/*
|
||||
* we have an INIT override of the
|
||||
* default
|
||||
*/
|
||||
if (initm.sinit_max_attempts)
|
||||
asoc->max_init_times = initm.sinit_max_attempts;
|
||||
if (initm.sinit_num_ostreams)
|
||||
asoc->pre_open_streams = initm.sinit_num_ostreams;
|
||||
if (initm.sinit_max_instreams)
|
||||
asoc->max_inbound_streams = initm.sinit_max_instreams;
|
||||
if (initm.sinit_max_init_timeo)
|
||||
asoc->initial_init_rto_max = initm.sinit_max_init_timeo;
|
||||
if (asoc->streamoutcnt < asoc->pre_open_streams) {
|
||||
struct sctp_stream_out *tmp_str;
|
||||
int had_lock = 0;
|
||||
|
||||
/* Default is NOT correct */
|
||||
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Ok, defout:%d pre_open:%d\n",
|
||||
asoc->streamoutcnt, asoc->pre_open_streams);
|
||||
/*
|
||||
* What happens if this
|
||||
* fails? we panic ...
|
||||
*/
|
||||
|
||||
if (hold_tcblock) {
|
||||
had_lock = 1;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
}
|
||||
SCTP_MALLOC(tmp_str,
|
||||
struct sctp_stream_out *,
|
||||
(asoc->pre_open_streams *
|
||||
sizeof(struct sctp_stream_out)),
|
||||
SCTP_M_STRMO);
|
||||
if (had_lock) {
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
}
|
||||
if (tmp_str != NULL) {
|
||||
SCTP_FREE(asoc->strmout, SCTP_M_STRMO);
|
||||
asoc->strmout = tmp_str;
|
||||
asoc->strm_realoutsize = asoc->streamoutcnt = asoc->pre_open_streams;
|
||||
} else {
|
||||
asoc->pre_open_streams = asoc->streamoutcnt;
|
||||
}
|
||||
for (i = 0; i < asoc->streamoutcnt; i++) {
|
||||
/*-
|
||||
* inbound side must be set
|
||||
* to 0xffff, also NOTE when
|
||||
* we get the INIT-ACK back
|
||||
* (for INIT sender) we MUST
|
||||
* reduce the count
|
||||
* (streamoutcnt) but first
|
||||
* check if we sent to any
|
||||
* of the upper streams that
|
||||
* were dropped (if some
|
||||
* were). Those that were
|
||||
* dropped must be notified
|
||||
* to the upper layer as
|
||||
* failed to send.
|
||||
*/
|
||||
asoc->strmout[i].next_sequence_sent = 0x0;
|
||||
TAILQ_INIT(&asoc->strmout[i].outqueue);
|
||||
asoc->strmout[i].stream_no = i;
|
||||
asoc->strmout[i].last_msg_incomplete = 0;
|
||||
asoc->ss_functions.sctp_ss_init_stream(&asoc->strmout[i], NULL);
|
||||
}
|
||||
}
|
||||
if (sctp_process_cmsgs_for_init(stcb, control, &error)) {
|
||||
sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_OUTPUT + SCTP_LOC_7);
|
||||
hold_tcblock = 0;
|
||||
stcb = NULL;
|
||||
goto out_unlocked;
|
||||
}
|
||||
}
|
||||
hold_tcblock = 1;
|
||||
/* out with the INIT */
|
||||
queue_only_for_init = 1;
|
||||
/*-
|
||||
|
@ -4196,11 +4196,11 @@ sctp_aloc_a_assoc_id(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
|
||||
return (0);
|
||||
}
|
||||
/*
|
||||
* We don't allow assoc id to be 0, this is needed otherwise if the
|
||||
* id were to wrap we would have issues with some socket options.
|
||||
* We don't allow assoc id to be one of SCTP_FUTURE_ASSOC,
|
||||
* SCTP_CURRENT_ASSOC and SCTP_ALL_ASSOC.
|
||||
*/
|
||||
if (inp->sctp_associd_counter == 0) {
|
||||
inp->sctp_associd_counter++;
|
||||
if (inp->sctp_associd_counter <= SCTP_ALL_ASSOC) {
|
||||
inp->sctp_associd_counter = SCTP_ALL_ASSOC + 1;
|
||||
}
|
||||
id = inp->sctp_associd_counter;
|
||||
inp->sctp_associd_counter++;
|
||||
@ -4793,7 +4793,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
/* Held for PD-API clear that. */
|
||||
sq->pdapi_aborted = 1;
|
||||
sq->held_length = 0;
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT) && (so != NULL)) {
|
||||
if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT) && (so != NULL)) {
|
||||
/*
|
||||
* Need to add a PD-API
|
||||
* aborted indication.
|
||||
|
@ -647,6 +647,8 @@ struct sctp_nonpad_sndrcvinfo {
|
||||
uint32_t sinfo_tsn;
|
||||
uint32_t sinfo_cumtsn;
|
||||
sctp_assoc_t sinfo_assoc_id;
|
||||
uint16_t sinfo_keynumber;
|
||||
uint16_t sinfo_keynumber_valid;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1201,6 +1203,7 @@ struct sctp_association {
|
||||
/* JRS 5/21/07 - CMT PF variable */
|
||||
uint8_t sctp_cmt_pf;
|
||||
uint8_t use_precise_time;
|
||||
uint32_t sctp_features;
|
||||
/*
|
||||
* The mapping array is used to track out of order sequences above
|
||||
* last_acked_seq. 0 indicates packet missing 1 indicates packet
|
||||
|
@ -47,6 +47,16 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
typedef uint32_t sctp_assoc_t;
|
||||
|
||||
#define SCTP_FUTURE_ASSOC 0
|
||||
#define SCTP_CURRENT_ASSOC 1
|
||||
#define SCTP_ALL_ASSOC 2
|
||||
|
||||
struct sctp_event {
|
||||
sctp_assoc_t se_assoc_id;
|
||||
uint16_t se_type;
|
||||
uint8_t se_on;
|
||||
};
|
||||
|
||||
/* Compatibility to previous define's */
|
||||
#define sctp_stream_reset_events sctp_stream_reset_event
|
||||
|
||||
@ -69,6 +79,14 @@ struct sctp_event_subscribe {
|
||||
#define SCTP_INIT 0x0001
|
||||
#define SCTP_SNDRCV 0x0002
|
||||
#define SCTP_EXTRCV 0x0003
|
||||
#define SCTP_SNDINFO 0x0004
|
||||
#define SCTP_RCVINFO 0x0005
|
||||
#define SCTP_NXTINFO 0x0006
|
||||
#define SCTP_PRINFO 0x0007
|
||||
#define SCTP_AUTHINFO 0x0008
|
||||
#define SCTP_DSTADDRV4 0x0009
|
||||
#define SCTP_DSTADDRV6 0x000a
|
||||
|
||||
/*
|
||||
* ancillary data structures
|
||||
*/
|
||||
@ -93,8 +111,8 @@ struct sctp_initmsg {
|
||||
*/
|
||||
|
||||
|
||||
#define SCTP_ALIGN_RESV_PAD 96
|
||||
#define SCTP_ALIGN_RESV_PAD_SHORT 80
|
||||
#define SCTP_ALIGN_RESV_PAD 92
|
||||
#define SCTP_ALIGN_RESV_PAD_SHORT 76
|
||||
|
||||
struct sctp_sndrcvinfo {
|
||||
uint16_t sinfo_stream;
|
||||
@ -106,6 +124,8 @@ struct sctp_sndrcvinfo {
|
||||
uint32_t sinfo_tsn;
|
||||
uint32_t sinfo_cumtsn;
|
||||
sctp_assoc_t sinfo_assoc_id;
|
||||
uint16_t sinfo_keynumber;
|
||||
uint16_t sinfo_keynumber_valid;
|
||||
uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD];
|
||||
};
|
||||
|
||||
@ -113,7 +133,6 @@ struct sctp_extrcvinfo {
|
||||
uint16_t sinfo_stream;
|
||||
uint16_t sinfo_ssn;
|
||||
uint16_t sinfo_flags;
|
||||
uint16_t sinfo_pr_policy;
|
||||
uint32_t sinfo_ppid;
|
||||
uint32_t sinfo_context;
|
||||
uint32_t sinfo_timetolive;
|
||||
@ -125,15 +144,79 @@ struct sctp_extrcvinfo {
|
||||
uint32_t sreinfo_next_aid;
|
||||
uint32_t sreinfo_next_length;
|
||||
uint32_t sreinfo_next_ppid;
|
||||
uint16_t sinfo_keynumber;
|
||||
uint16_t sinfo_keynumber_valid;
|
||||
uint8_t __reserve_pad[SCTP_ALIGN_RESV_PAD_SHORT];
|
||||
};
|
||||
|
||||
struct sctp_sndinfo {
|
||||
uint16_t snd_sid;
|
||||
uint16_t snd_flags;
|
||||
uint32_t snd_ppid;
|
||||
uint32_t snd_context;
|
||||
sctp_assoc_t snd_assoc_id;
|
||||
};
|
||||
|
||||
struct sctp_prinfo {
|
||||
uint16_t pr_policy;
|
||||
uint32_t pr_value;
|
||||
};
|
||||
|
||||
struct sctp_authinfo {
|
||||
uint16_t auth_keyid;
|
||||
};
|
||||
|
||||
struct sctp_rcvinfo {
|
||||
uint16_t rcv_sid;
|
||||
uint16_t rcv_ssn;
|
||||
uint16_t rcv_flags;
|
||||
uint32_t rcv_ppid;
|
||||
uint32_t rcv_tsn;
|
||||
uint32_t rcv_cumtsn;
|
||||
uint32_t rcv_context;
|
||||
sctp_assoc_t rcv_assoc_id;
|
||||
};
|
||||
|
||||
struct sctp_nxtinfo {
|
||||
uint16_t nxt_sid;
|
||||
uint16_t nxt_flags;
|
||||
uint32_t nxt_ppid;
|
||||
uint32_t nxt_length;
|
||||
sctp_assoc_t nxt_assoc_id;
|
||||
};
|
||||
|
||||
#define SCTP_NO_NEXT_MSG 0x0000
|
||||
#define SCTP_NEXT_MSG_AVAIL 0x0001
|
||||
#define SCTP_NEXT_MSG_ISCOMPLETE 0x0002
|
||||
#define SCTP_NEXT_MSG_IS_UNORDERED 0x0004
|
||||
#define SCTP_NEXT_MSG_IS_NOTIFICATION 0x0008
|
||||
|
||||
struct sctp_recvv_rn {
|
||||
struct sctp_rcvinfo recvv_rcvinfo;
|
||||
struct sctp_nxtinfo recvv_nxtinfo;
|
||||
};
|
||||
|
||||
#define SCTP_RECVV_NOINFO 0
|
||||
#define SCTP_RECVV_RCVINFO 1
|
||||
#define SCTP_RECVV_NXTINFO 2
|
||||
#define SCTP_RECVV_RN 3
|
||||
|
||||
#define SCTP_SENDV_SNDINFO 1
|
||||
#define SCTP_SENDV_PRINFO 2
|
||||
#define SCTP_SENDV_AUTHINFO 3
|
||||
#define SCTP_SENDV_SPA 4
|
||||
|
||||
struct sctp_sendv_spa {
|
||||
uint32_t sendv_flags;
|
||||
struct sctp_sndinfo sendv_sndinfo;
|
||||
struct sctp_prinfo sendv_prinfo;
|
||||
struct sctp_authinfo sendv_authinfo;
|
||||
};
|
||||
|
||||
#define SCTP_SEND_SNDINFO_VALID 0x00000001
|
||||
#define SCTP_SEND_PRINFO_VALID 0x00000002
|
||||
#define SCTP_SEND_AUTHINFO_VALID 0x00000004
|
||||
|
||||
struct sctp_snd_all_completes {
|
||||
uint16_t sall_stream;
|
||||
uint16_t sall_flags;
|
||||
@ -144,6 +227,8 @@ struct sctp_snd_all_completes {
|
||||
};
|
||||
|
||||
/* Flags that go into the sinfo->sinfo_flags field */
|
||||
#define SCTP_NOTIFICATION 0x0010 /* next message is a notification */
|
||||
#define SCTP_COMPLETE 0x0020 /* next message is complete */
|
||||
#define SCTP_EOF 0x0100 /* Start shutdown procedures */
|
||||
#define SCTP_ABORT 0x0200 /* Send an ABORT to peer */
|
||||
#define SCTP_UNORDERED 0x0400 /* Message is un-ordered */
|
||||
@ -152,7 +237,7 @@ struct sctp_snd_all_completes {
|
||||
#define SCTP_EOR 0x2000 /* end of message signal */
|
||||
#define SCTP_SACK_IMMEDIATELY 0x4000 /* Set I-Bit */
|
||||
|
||||
#define INVALID_SINFO_FLAG(x) (((x) & 0xffffff00 \
|
||||
#define INVALID_SINFO_FLAG(x) (((x) & 0xfffffff0 \
|
||||
& ~(SCTP_EOF | SCTP_ABORT | SCTP_UNORDERED |\
|
||||
SCTP_ADDR_OVER | SCTP_SENDALL | SCTP_EOR |\
|
||||
SCTP_SACK_IMMEDIATELY)) != 0)
|
||||
@ -163,7 +248,7 @@ struct sctp_snd_all_completes {
|
||||
#define SCTP_PR_SCTP_BUF 0x0002/* Buffer based PR-SCTP */
|
||||
#define SCTP_PR_SCTP_RTX 0x0003/* Number of retransmissions based PR-SCTP */
|
||||
|
||||
#define PR_SCTP_POLICY(x) ((x) & 0xff)
|
||||
#define PR_SCTP_POLICY(x) ((x) & 0x0f)
|
||||
#define PR_SCTP_ENABLED(x) (PR_SCTP_POLICY(x) != 0)
|
||||
#define PR_SCTP_TTL_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_TTL)
|
||||
#define PR_SCTP_BUF_ENABLED(x) (PR_SCTP_POLICY(x) == SCTP_PR_SCTP_BUF)
|
||||
@ -1132,26 +1217,34 @@ int sctp_getladdrs __P((int, sctp_assoc_t, struct sockaddr **));
|
||||
void sctp_freeladdrs __P((struct sockaddr *));
|
||||
int sctp_opt_info __P((int, sctp_assoc_t, int, void *, socklen_t *));
|
||||
|
||||
/* deprecated */
|
||||
ssize_t sctp_sendmsg
|
||||
__P((int, const void *, size_t,
|
||||
const struct sockaddr *,
|
||||
__P((int, const void *, size_t, const struct sockaddr *,
|
||||
socklen_t, uint32_t, uint32_t, uint16_t, uint32_t, uint32_t));
|
||||
|
||||
ssize_t sctp_send __P((int sd, const void *msg, size_t len,
|
||||
const struct sctp_sndrcvinfo *sinfo, int flags));
|
||||
/* deprecated */
|
||||
ssize_t sctp_send __P((int, const void *, size_t,
|
||||
const struct sctp_sndrcvinfo *, int));
|
||||
|
||||
ssize_t sctp_sendx __P((int sd, const void *msg, size_t len,
|
||||
struct sockaddr *addrs, int addrcnt,
|
||||
struct sctp_sndrcvinfo *sinfo, int flags));
|
||||
/* deprecated */
|
||||
ssize_t sctp_sendx __P((int, const void *, size_t, struct sockaddr *,
|
||||
int, struct sctp_sndrcvinfo *, int));
|
||||
|
||||
ssize_t sctp_sendmsgx __P((int sd, const void *, size_t,
|
||||
struct sockaddr *, int,
|
||||
uint32_t, uint32_t, uint16_t, uint32_t, uint32_t));
|
||||
/* deprecated */
|
||||
ssize_t sctp_sendmsgx __P((int sd, const void *, size_t, struct sockaddr *,
|
||||
int, uint32_t, uint32_t, uint16_t, uint32_t, uint32_t));
|
||||
|
||||
sctp_assoc_t sctp_getassocid __P((int sd, struct sockaddr *sa));
|
||||
sctp_assoc_t sctp_getassocid __P((int, struct sockaddr *));
|
||||
|
||||
ssize_t sctp_recvmsg __P((int, void *, size_t, struct sockaddr *,
|
||||
socklen_t *, struct sctp_sndrcvinfo *, int *));
|
||||
/* deprecated */
|
||||
ssize_t sctp_recvmsg __P((int, void *, size_t, struct sockaddr *, socklen_t *,
|
||||
struct sctp_sndrcvinfo *, int *));
|
||||
|
||||
ssize_t sctp_sendv __P((int, const struct iovec *, int, struct sockaddr *,
|
||||
int, void *, socklen_t, unsigned int, int));
|
||||
|
||||
ssize_t sctp_recvv __P((int, const struct iovec *, int, struct sockaddr *,
|
||||
socklen_t *, void *, socklen_t *, unsigned int *, int *));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -50,6 +50,30 @@ extern struct pr_usrreqs sctp_usrreqs;
|
||||
#define sctp_is_feature_on(inp, feature) ((inp->sctp_features & feature) == feature)
|
||||
#define sctp_is_feature_off(inp, feature) ((inp->sctp_features & feature) == 0)
|
||||
|
||||
#define sctp_stcb_feature_on(inp, stcb, feature) {\
|
||||
if (stcb) { \
|
||||
stcb->asoc.sctp_features |= feature; \
|
||||
} else { \
|
||||
inp->sctp_features |= feature; \
|
||||
} \
|
||||
}
|
||||
#define sctp_stcb_feature_off(inp, stcb, feature) {\
|
||||
if (stcb) { \
|
||||
stcb->asoc.sctp_features &= ~feature; \
|
||||
} else { \
|
||||
inp->sctp_features &= ~feature; \
|
||||
} \
|
||||
}
|
||||
#define sctp_stcb_is_feature_on(inp, stcb, feature) \
|
||||
(((stcb != NULL) && \
|
||||
((stcb->asoc.sctp_features & feature) == feature)) || \
|
||||
((stcb == NULL) && \
|
||||
((inp->sctp_features & feature) == feature)))
|
||||
#define sctp_stcb_is_feature_off(inp, stcb, feature) \
|
||||
(((stcb != NULL) && \
|
||||
((stcb->asoc.sctp_features & feature) == 0)) || \
|
||||
((stcb == NULL) && \
|
||||
((inp->sctp_features & feature) == 0)))
|
||||
|
||||
/* managing mobility_feature in inpcb (by micchie) */
|
||||
#define sctp_mobility_feature_on(inp, feature) (inp->sctp_mobility_features |= feature)
|
||||
|
@ -923,6 +923,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
|
||||
asoc->sctp_nr_sack_on_off = (uint8_t) SCTP_BASE_SYSCTL(sctp_nr_sack_on_off);
|
||||
asoc->sctp_cmt_pf = (uint8_t) SCTP_BASE_SYSCTL(sctp_cmt_pf);
|
||||
asoc->sctp_frag_point = m->sctp_frag_point;
|
||||
asoc->sctp_features = m->sctp_features;
|
||||
#ifdef INET
|
||||
asoc->default_tos = m->ip_inp.inp.inp_ip_tos;
|
||||
#else
|
||||
@ -2760,7 +2761,7 @@ sctp_notify_assoc_change(uint32_t event, struct sctp_tcb *stcb,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
@ -2831,7 +2832,7 @@ sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
|
||||
struct sctp_paddr_change *spc;
|
||||
struct sctp_queued_to_read *control;
|
||||
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT)) {
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
@ -2914,7 +2915,7 @@ sctp_notify_send_failed(struct sctp_tcb *stcb, uint32_t error,
|
||||
struct sctp_queued_to_read *control;
|
||||
int length;
|
||||
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVSENDFAILEVNT)) {
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT)) {
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
@ -2997,7 +2998,7 @@ sctp_notify_send_failed2(struct sctp_tcb *stcb, uint32_t error,
|
||||
struct sctp_queued_to_read *control;
|
||||
int length;
|
||||
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVSENDFAILEVNT)) {
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT)) {
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
@ -3067,7 +3068,7 @@ sctp_notify_adaptation_layer(struct sctp_tcb *stcb,
|
||||
struct sctp_adaptation_event *sai;
|
||||
struct sctp_queued_to_read *control;
|
||||
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT)) {
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
@ -3118,7 +3119,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb, uint32_t error,
|
||||
struct sctp_queued_to_read *control;
|
||||
struct sockbuf *sb;
|
||||
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_PDAPIEVNT)) {
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_PDAPIEVNT)) {
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
@ -3231,7 +3232,7 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
#endif
|
||||
}
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) {
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)) {
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
@ -3278,7 +3279,7 @@ sctp_notify_sender_dry_event(struct sctp_tcb *stcb,
|
||||
struct sctp_sender_dry_event *event;
|
||||
struct sctp_queued_to_read *control;
|
||||
|
||||
if (sctp_is_feature_off(stcb->sctp_ep, SCTP_PCB_FLAGS_DRYEVNT)) {
|
||||
if (sctp_stcb_is_feature_off(stcb->sctp_ep, stcb, SCTP_PCB_FLAGS_DRYEVNT)) {
|
||||
/* event not enabled */
|
||||
return;
|
||||
}
|
||||
@ -5490,7 +5491,8 @@ sctp_sorecvmsg(struct socket *so,
|
||||
if ((sinfo) && filling_sinfo) {
|
||||
memcpy(sinfo, control, sizeof(struct sctp_nonpad_sndrcvinfo));
|
||||
nxt = TAILQ_NEXT(control, next);
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO)) {
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
|
||||
sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) {
|
||||
struct sctp_extrcvinfo *s_extra;
|
||||
|
||||
s_extra = (struct sctp_extrcvinfo *)sinfo;
|
||||
@ -5997,7 +5999,8 @@ sctp_sorecvmsg(struct socket *so,
|
||||
if (((out_flags & MSG_EOR) == 0) &&
|
||||
((in_flags & MSG_PEEK) == 0) &&
|
||||
(sinfo) &&
|
||||
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO))) {
|
||||
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO) ||
|
||||
sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO))) {
|
||||
struct sctp_extrcvinfo *s_extra;
|
||||
|
||||
s_extra = (struct sctp_extrcvinfo *)sinfo;
|
||||
@ -6147,8 +6150,9 @@ sctp_soreceive(struct socket *so,
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTPUTIL, EINVAL);
|
||||
return (EINVAL);
|
||||
}
|
||||
if ((sctp_is_feature_off(inp,
|
||||
SCTP_PCB_FLAGS_RECVDATAIOEVNT)) ||
|
||||
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT) &&
|
||||
sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO) &&
|
||||
sctp_is_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO)) ||
|
||||
(controlp == NULL)) {
|
||||
/* user does not want the sndrcv ctl */
|
||||
filling_sinfo = 0;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Jake Burkholder.
|
||||
* Copyright (c) 2007 - 2011 Marius Strobl <marius@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -136,8 +137,11 @@ extern char tl_ipi_tlb_range_demap[];
|
||||
static __inline void
|
||||
ipi_all_but_self(u_int ipi)
|
||||
{
|
||||
cpuset_t cpus;
|
||||
|
||||
cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)tl_ipi_level, ipi);
|
||||
cpus = all_cpus;
|
||||
CPU_CLR(PCPU_GET(cpuid), &cpus);
|
||||
cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_level, ipi);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
@ -167,8 +171,9 @@ ipi_dcache_page_inval(void *func, vm_paddr_t pa)
|
||||
ica = &ipi_cache_args;
|
||||
mtx_lock_spin(&ipi_mtx);
|
||||
ica->ica_mask = all_cpus;
|
||||
CPU_CLR(PCPU_GET(cpuid), &ica->ica_mask);
|
||||
ica->ica_pa = pa;
|
||||
cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
|
||||
cpu_ipi_selected(ica->ica_mask, 0, (u_long)func, (u_long)ica);
|
||||
return (&ica->ica_mask);
|
||||
}
|
||||
|
||||
@ -183,8 +188,9 @@ ipi_icache_page_inval(void *func, vm_paddr_t pa)
|
||||
ica = &ipi_cache_args;
|
||||
mtx_lock_spin(&ipi_mtx);
|
||||
ica->ica_mask = all_cpus;
|
||||
CPU_CLR(PCPU_GET(cpuid), &ica->ica_mask);
|
||||
ica->ica_pa = pa;
|
||||
cpu_ipi_selected(PCPU_GET(other_cpus), 0, (u_long)func, (u_long)ica);
|
||||
cpu_ipi_selected(ica->ica_mask, 0, (u_long)func, (u_long)ica);
|
||||
return (&ica->ica_mask);
|
||||
}
|
||||
|
||||
@ -198,8 +204,7 @@ ipi_rd(u_int cpu, void *func, u_long *val)
|
||||
sched_pin();
|
||||
ira = &ipi_rd_args;
|
||||
mtx_lock_spin(&ipi_mtx);
|
||||
ira->ira_mask = PCPU_GET(cpumask);
|
||||
CPU_SET(cpu, &ira->ira_mask);
|
||||
CPU_SETOF(cpu, &ira->ira_mask);
|
||||
ira->ira_val = val;
|
||||
cpu_ipi_single(cpu, 0, (u_long)func, (u_long)ira);
|
||||
return (&ira->ira_mask);
|
||||
@ -215,7 +220,8 @@ ipi_tlb_context_demap(struct pmap *pm)
|
||||
return (NULL);
|
||||
sched_pin();
|
||||
cpus = pm->pm_active;
|
||||
CPU_AND(&cpus, PCPU_PTR(other_cpus));
|
||||
CPU_AND(&cpus, &all_cpus);
|
||||
CPU_CLR(PCPU_GET(cpuid), &cpus);
|
||||
if (CPU_EMPTY(&cpus)) {
|
||||
sched_unpin();
|
||||
return (NULL);
|
||||
@ -223,7 +229,6 @@ ipi_tlb_context_demap(struct pmap *pm)
|
||||
ita = &ipi_tlb_args;
|
||||
mtx_lock_spin(&ipi_mtx);
|
||||
ita->ita_mask = cpus;
|
||||
CPU_OR(&ita->ita_mask, PCPU_PTR(cpumask));
|
||||
ita->ita_pmap = pm;
|
||||
cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_context_demap,
|
||||
(u_long)ita);
|
||||
@ -240,7 +245,8 @@ ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
|
||||
return (NULL);
|
||||
sched_pin();
|
||||
cpus = pm->pm_active;
|
||||
CPU_AND(&cpus, PCPU_PTR(other_cpus));
|
||||
CPU_AND(&cpus, &all_cpus);
|
||||
CPU_CLR(PCPU_GET(cpuid), &cpus);
|
||||
if (CPU_EMPTY(&cpus)) {
|
||||
sched_unpin();
|
||||
return (NULL);
|
||||
@ -248,7 +254,6 @@ ipi_tlb_page_demap(struct pmap *pm, vm_offset_t va)
|
||||
ita = &ipi_tlb_args;
|
||||
mtx_lock_spin(&ipi_mtx);
|
||||
ita->ita_mask = cpus;
|
||||
CPU_OR(&ita->ita_mask, PCPU_PTR(cpumask));
|
||||
ita->ita_pmap = pm;
|
||||
ita->ita_va = va;
|
||||
cpu_ipi_selected(cpus, 0, (u_long)tl_ipi_tlb_page_demap, (u_long)ita);
|
||||
@ -265,7 +270,8 @@ ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
|
||||
return (NULL);
|
||||
sched_pin();
|
||||
cpus = pm->pm_active;
|
||||
CPU_AND(&cpus, PCPU_PTR(other_cpus));
|
||||
CPU_AND(&cpus, &all_cpus);
|
||||
CPU_CLR(PCPU_GET(cpuid), &cpus);
|
||||
if (CPU_EMPTY(&cpus)) {
|
||||
sched_unpin();
|
||||
return (NULL);
|
||||
@ -273,7 +279,6 @@ ipi_tlb_range_demap(struct pmap *pm, vm_offset_t start, vm_offset_t end)
|
||||
ita = &ipi_tlb_args;
|
||||
mtx_lock_spin(&ipi_mtx);
|
||||
ita->ita_mask = cpus;
|
||||
CPU_OR(&ita->ita_mask, PCPU_PTR(cpumask));
|
||||
ita->ita_pmap = pm;
|
||||
ita->ita_start = start;
|
||||
ita->ita_end = end;
|
||||
@ -288,7 +293,6 @@ ipi_wait(void *cookie)
|
||||
volatile cpuset_t *mask;
|
||||
|
||||
if ((mask = cookie) != NULL) {
|
||||
CPU_NAND_ATOMIC(mask, PCPU_PTR(cpumask));
|
||||
while (!CPU_EMPTY(mask))
|
||||
;
|
||||
mtx_unlock_spin(&ipi_mtx);
|
||||
|
@ -116,7 +116,6 @@ static ufs2_daddr_t ffs_clusteralloc(struct inode *, u_int, ufs2_daddr_t, int,
|
||||
static ino_t ffs_dirpref(struct inode *);
|
||||
static ufs2_daddr_t ffs_fragextend(struct inode *, u_int, ufs2_daddr_t,
|
||||
int, int);
|
||||
static void ffs_fserr(struct fs *, ino_t, char *);
|
||||
static ufs2_daddr_t ffs_hashalloc
|
||||
(struct inode *, u_int, ufs2_daddr_t, int, int, allocfcn_t *);
|
||||
static ufs2_daddr_t ffs_nodealloccg(struct inode *, u_int, ufs2_daddr_t, int,
|
||||
@ -223,7 +222,7 @@ ffs_alloc(ip, lbn, bpref, size, flags, cred, bnp)
|
||||
goto retry;
|
||||
}
|
||||
UFS_UNLOCK(ump);
|
||||
if (ppsratecheck(&lastfail, &curfail, 1)) {
|
||||
if (reclaimed > 0 && ppsratecheck(&lastfail, &curfail, 1)) {
|
||||
ffs_fserr(fs, ip->i_number, "filesystem full");
|
||||
uprintf("\n%s: write failed, filesystem is full\n",
|
||||
fs->fs_fsmnt);
|
||||
@ -391,7 +390,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp)
|
||||
bp->b_blkno = fsbtodb(fs, bno);
|
||||
if (!DOINGSOFTDEP(vp))
|
||||
ffs_blkfree(ump, fs, ip->i_devvp, bprev, (long)osize,
|
||||
ip->i_number, NULL);
|
||||
ip->i_number, vp->v_type, NULL);
|
||||
delta = btodb(nsize - osize);
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta);
|
||||
if (flags & IO_EXT)
|
||||
@ -432,7 +431,7 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp)
|
||||
UFS_UNLOCK(ump);
|
||||
if (bp)
|
||||
brelse(bp);
|
||||
if (ppsratecheck(&lastfail, &curfail, 1)) {
|
||||
if (reclaimed > 0 && ppsratecheck(&lastfail, &curfail, 1)) {
|
||||
ffs_fserr(fs, ip->i_number, "filesystem full");
|
||||
uprintf("\n%s: write failed, filesystem is full\n",
|
||||
fs->fs_fsmnt);
|
||||
@ -671,7 +670,7 @@ ffs_reallocblks_ufs1(ap)
|
||||
if (!DOINGSOFTDEP(vp))
|
||||
ffs_blkfree(ump, fs, ip->i_devvp,
|
||||
dbtofsb(fs, buflist->bs_children[i]->b_blkno),
|
||||
fs->fs_bsize, ip->i_number, NULL);
|
||||
fs->fs_bsize, ip->i_number, vp->v_type, NULL);
|
||||
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
|
||||
#ifdef INVARIANTS
|
||||
if (!ffs_checkblk(ip,
|
||||
@ -879,7 +878,7 @@ ffs_reallocblks_ufs2(ap)
|
||||
if (!DOINGSOFTDEP(vp))
|
||||
ffs_blkfree(ump, fs, ip->i_devvp,
|
||||
dbtofsb(fs, buflist->bs_children[i]->b_blkno),
|
||||
fs->fs_bsize, ip->i_number, NULL);
|
||||
fs->fs_bsize, ip->i_number, vp->v_type, NULL);
|
||||
buflist->bs_children[i]->b_blkno = fsbtodb(fs, blkno);
|
||||
#ifdef INVARIANTS
|
||||
if (!ffs_checkblk(ip,
|
||||
@ -1881,7 +1880,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd)
|
||||
printf("dev=%s, bno = %jd, bsize = %ld, size = %ld, fs = %s\n",
|
||||
devtoname(dev), (intmax_t)bno, (long)fs->fs_bsize,
|
||||
size, fs->fs_fsmnt);
|
||||
panic("ffs_blkfree: bad size");
|
||||
panic("ffs_blkfree_cg: bad size");
|
||||
}
|
||||
#endif
|
||||
if ((u_int)bno >= fs->fs_size) {
|
||||
@ -1915,7 +1914,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd)
|
||||
}
|
||||
printf("dev = %s, block = %jd, fs = %s\n",
|
||||
devtoname(dev), (intmax_t)bno, fs->fs_fsmnt);
|
||||
panic("ffs_blkfree: freeing free block");
|
||||
panic("ffs_blkfree_cg: freeing free block");
|
||||
}
|
||||
ffs_setblock(fs, blksfree, fragno);
|
||||
ffs_clusteracct(fs, cgp, fragno, 1);
|
||||
@ -1938,7 +1937,7 @@ ffs_blkfree_cg(ump, fs, devvp, bno, size, inum, dephd)
|
||||
printf("dev = %s, block = %jd, fs = %s\n",
|
||||
devtoname(dev), (intmax_t)(bno + i),
|
||||
fs->fs_fsmnt);
|
||||
panic("ffs_blkfree: freeing free frag");
|
||||
panic("ffs_blkfree_cg: freeing free frag");
|
||||
}
|
||||
setbit(blksfree, cgbno + i);
|
||||
}
|
||||
@ -2014,13 +2013,14 @@ ffs_blkfree_trim_completed(bip)
|
||||
}
|
||||
|
||||
void
|
||||
ffs_blkfree(ump, fs, devvp, bno, size, inum, dephd)
|
||||
ffs_blkfree(ump, fs, devvp, bno, size, inum, vtype, dephd)
|
||||
struct ufsmount *ump;
|
||||
struct fs *fs;
|
||||
struct vnode *devvp;
|
||||
ufs2_daddr_t bno;
|
||||
long size;
|
||||
ino_t inum;
|
||||
enum vtype vtype;
|
||||
struct workhead *dephd;
|
||||
{
|
||||
struct mount *mp;
|
||||
@ -2035,7 +2035,7 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum, dephd)
|
||||
*/
|
||||
if (devvp->v_type != VREG &&
|
||||
(devvp->v_vflag & VV_COPYONWRITE) &&
|
||||
ffs_snapblkfree(fs, devvp, bno, size, inum, dephd)) {
|
||||
ffs_snapblkfree(fs, devvp, bno, size, inum, vtype, dephd)) {
|
||||
return;
|
||||
}
|
||||
if (!ump->um_candelete) {
|
||||
@ -2335,7 +2335,7 @@ ffs_mapsearch(fs, cgp, bpref, allocsiz)
|
||||
* The form of the error message is:
|
||||
* fs: error message
|
||||
*/
|
||||
static void
|
||||
void
|
||||
ffs_fserr(fs, inum, cp)
|
||||
struct fs *fs;
|
||||
ino_t inum;
|
||||
@ -2572,7 +2572,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
|
||||
if (blksize > blkcnt)
|
||||
blksize = blkcnt;
|
||||
ffs_blkfree(ump, fs, ump->um_devvp, blkno,
|
||||
blksize * fs->fs_fsize, ROOTINO, NULL);
|
||||
blksize * fs->fs_fsize, ROOTINO, VDIR, NULL);
|
||||
blkno += blksize;
|
||||
blkcnt -= blksize;
|
||||
blksize = fs->fs_frag;
|
||||
|
@ -105,6 +105,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
|
||||
ufs2_daddr_t *lbns_remfree, lbns[NIADDR + 1];
|
||||
int unwindidx = -1;
|
||||
int saved_inbdflush;
|
||||
static struct timeval lastfail;
|
||||
static int curfail;
|
||||
int reclaimed;
|
||||
|
||||
ip = VTOI(vp);
|
||||
@ -308,6 +310,11 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
|
||||
UFS_UNLOCK(ump);
|
||||
goto retry;
|
||||
}
|
||||
if (ppsratecheck(&lastfail, &curfail, 1)) {
|
||||
ffs_fserr(fs, ip->i_number, "filesystem full");
|
||||
uprintf("\n%s: write failed, filesystem "
|
||||
"is full\n", fs->fs_fsmnt);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
nb = newb;
|
||||
@ -370,6 +377,11 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
|
||||
UFS_UNLOCK(ump);
|
||||
goto retry;
|
||||
}
|
||||
if (ppsratecheck(&lastfail, &curfail, 1)) {
|
||||
ffs_fserr(fs, ip->i_number, "filesystem full");
|
||||
uprintf("\n%s: write failed, filesystem "
|
||||
"is full\n", fs->fs_fsmnt);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
nb = newb;
|
||||
@ -494,7 +506,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size,
|
||||
*/
|
||||
for (blkp = allociblk; blkp < allocblk; blkp++) {
|
||||
ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize,
|
||||
ip->i_number, NULL);
|
||||
ip->i_number, vp->v_type, NULL);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@ -523,6 +535,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
|
||||
int deallocated, osize, nsize, num, i, error;
|
||||
int unwindidx = -1;
|
||||
int saved_inbdflush;
|
||||
static struct timeval lastfail;
|
||||
static int curfail;
|
||||
int reclaimed;
|
||||
|
||||
ip = VTOI(vp);
|
||||
@ -836,6 +850,11 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
|
||||
UFS_UNLOCK(ump);
|
||||
goto retry;
|
||||
}
|
||||
if (ppsratecheck(&lastfail, &curfail, 1)) {
|
||||
ffs_fserr(fs, ip->i_number, "filesystem full");
|
||||
uprintf("\n%s: write failed, filesystem "
|
||||
"is full\n", fs->fs_fsmnt);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
nb = newb;
|
||||
@ -898,6 +917,11 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
|
||||
UFS_UNLOCK(ump);
|
||||
goto retry;
|
||||
}
|
||||
if (ppsratecheck(&lastfail, &curfail, 1)) {
|
||||
ffs_fserr(fs, ip->i_number, "filesystem full");
|
||||
uprintf("\n%s: write failed, filesystem "
|
||||
"is full\n", fs->fs_fsmnt);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
nb = newb;
|
||||
@ -1028,7 +1052,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size,
|
||||
*/
|
||||
for (blkp = allociblk; blkp < allocblk; blkp++) {
|
||||
ffs_blkfree(ump, fs, ip->i_devvp, *blkp, fs->fs_bsize,
|
||||
ip->i_number, NULL);
|
||||
ip->i_number, vp->v_type, NULL);
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#ifndef _UFS_FFS_EXTERN_H
|
||||
#define _UFS_FFS_EXTERN_H
|
||||
|
||||
enum vtype;
|
||||
struct buf;
|
||||
struct cg;
|
||||
struct fid;
|
||||
@ -57,7 +58,7 @@ int ffs_balloc_ufs2(struct vnode *a_vp, off_t a_startoffset, int a_size,
|
||||
struct ucred *a_cred, int a_flags, struct buf **a_bpp);
|
||||
int ffs_blkatoff(struct vnode *, off_t, char **, struct buf **);
|
||||
void ffs_blkfree(struct ufsmount *, struct fs *, struct vnode *,
|
||||
ufs2_daddr_t, long, ino_t, struct workhead *);
|
||||
ufs2_daddr_t, long, ino_t, enum vtype, struct workhead *);
|
||||
ufs2_daddr_t ffs_blkpref_ufs1(struct inode *, ufs_lbn_t, int, ufs1_daddr_t *);
|
||||
ufs2_daddr_t ffs_blkpref_ufs2(struct inode *, ufs_lbn_t, int, ufs2_daddr_t *);
|
||||
int ffs_checkfreefile(struct fs *, struct vnode *, ino_t);
|
||||
@ -69,6 +70,7 @@ int ffs_flushfiles(struct mount *, int, struct thread *);
|
||||
void ffs_fragacct(struct fs *, int, int32_t [], int);
|
||||
int ffs_freefile(struct ufsmount *, struct fs *, struct vnode *, ino_t,
|
||||
int, struct workhead *);
|
||||
void ffs_fserr(struct fs *, ino_t, char *);
|
||||
int ffs_isblock(struct fs *, u_char *, ufs1_daddr_t);
|
||||
int ffs_isfreeblock(struct fs *, u_char *, ufs1_daddr_t);
|
||||
void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t);
|
||||
@ -81,7 +83,7 @@ int ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t,
|
||||
int ffs_sbupdate(struct ufsmount *, int, int);
|
||||
void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t);
|
||||
int ffs_snapblkfree(struct fs *, struct vnode *, ufs2_daddr_t, long, ino_t,
|
||||
struct workhead *);
|
||||
enum vtype, struct workhead *);
|
||||
void ffs_snapremove(struct vnode *vp);
|
||||
int ffs_snapshot(struct mount *mp, char *snapfile);
|
||||
void ffs_snapshot_mount(struct mount *mp);
|
||||
|
@ -235,7 +235,8 @@ ffs_truncate(vp, length, flags, cred, td)
|
||||
if (oldblks[i] == 0)
|
||||
continue;
|
||||
ffs_blkfree(ump, fs, ip->i_devvp, oldblks[i],
|
||||
sblksize(fs, osize, i), ip->i_number, NULL);
|
||||
sblksize(fs, osize, i), ip->i_number,
|
||||
vp->v_type, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -435,7 +436,8 @@ ffs_truncate(vp, length, flags, cred, td)
|
||||
if (lastiblock[level] < 0) {
|
||||
DIP_SET(ip, i_ib[level], 0);
|
||||
ffs_blkfree(ump, fs, ip->i_devvp, bn,
|
||||
fs->fs_bsize, ip->i_number, NULL);
|
||||
fs->fs_bsize, ip->i_number,
|
||||
vp->v_type, NULL);
|
||||
blocksreleased += nblocks;
|
||||
}
|
||||
}
|
||||
@ -455,7 +457,7 @@ ffs_truncate(vp, length, flags, cred, td)
|
||||
DIP_SET(ip, i_db[i], 0);
|
||||
bsize = blksize(fs, ip, i);
|
||||
ffs_blkfree(ump, fs, ip->i_devvp, bn, bsize, ip->i_number,
|
||||
NULL);
|
||||
vp->v_type, NULL);
|
||||
blocksreleased += btodb(bsize);
|
||||
}
|
||||
if (lastblock < 0)
|
||||
@ -487,7 +489,7 @@ ffs_truncate(vp, length, flags, cred, td)
|
||||
*/
|
||||
bn += numfrags(fs, newspace);
|
||||
ffs_blkfree(ump, fs, ip->i_devvp, bn,
|
||||
oldspace - newspace, ip->i_number, NULL);
|
||||
oldspace - newspace, ip->i_number, vp->v_type, NULL);
|
||||
blocksreleased += btodb(oldspace - newspace);
|
||||
}
|
||||
}
|
||||
@ -634,7 +636,7 @@ ffs_indirtrunc(ip, lbn, dbn, lastbn, level, countp)
|
||||
blocksreleased += blkcount;
|
||||
}
|
||||
ffs_blkfree(ip->i_ump, fs, ip->i_devvp, nb, fs->fs_bsize,
|
||||
ip->i_number, NULL);
|
||||
ip->i_number, vp->v_type, NULL);
|
||||
blocksreleased += nblocks;
|
||||
}
|
||||
|
||||
|
@ -81,12 +81,13 @@ ffs_snapshot(mp, snapfile)
|
||||
}
|
||||
|
||||
int
|
||||
ffs_snapblkfree(fs, devvp, bno, size, inum, wkhd)
|
||||
ffs_snapblkfree(fs, devvp, bno, size, inum, vtype, wkhd)
|
||||
struct fs *fs;
|
||||
struct vnode *devvp;
|
||||
ufs2_daddr_t bno;
|
||||
long size;
|
||||
ino_t inum;
|
||||
enum vtype vtype;
|
||||
struct workhead *wkhd;
|
||||
{
|
||||
return (EINVAL);
|
||||
@ -174,8 +175,10 @@ static int ffs_bp_snapblk(struct vnode *, struct buf *);
|
||||
* To ensure the consistency of snapshots across crashes, we must
|
||||
* synchronously write out copied blocks before allowing the
|
||||
* originals to be modified. Because of the rather severe speed
|
||||
* penalty that this imposes, the following flag allows this
|
||||
* crash persistence to be disabled.
|
||||
* penalty that this imposes, the code normally only ensures
|
||||
* persistence for the filesystem metadata contained within a
|
||||
* snapshot. Setting the following flag allows this crash
|
||||
* persistence to be enabled for file contents.
|
||||
*/
|
||||
int dopersistence = 0;
|
||||
|
||||
@ -582,7 +585,7 @@ ffs_snapshot(mp, snapfile)
|
||||
if (len != 0 && len < fs->fs_bsize) {
|
||||
ffs_blkfree(ump, copy_fs, vp,
|
||||
DIP(xp, i_db[loc]), len, xp->i_number,
|
||||
NULL);
|
||||
xvp->v_type, NULL);
|
||||
blkno = DIP(xp, i_db[loc]);
|
||||
DIP_SET(xp, i_db[loc], 0);
|
||||
}
|
||||
@ -1245,7 +1248,8 @@ mapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
|
||||
*ip->i_snapblklist++ = lblkno;
|
||||
if (blkno == BLK_SNAP)
|
||||
blkno = blkstofrags(fs, lblkno);
|
||||
ffs_blkfree(ip->i_ump, fs, vp, blkno, fs->fs_bsize, inum, NULL);
|
||||
ffs_blkfree(ip->i_ump, fs, vp, blkno, fs->fs_bsize, inum,
|
||||
vp->v_type, NULL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -1528,7 +1532,8 @@ mapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, expungetype)
|
||||
*ip->i_snapblklist++ = lblkno;
|
||||
if (blkno == BLK_SNAP)
|
||||
blkno = blkstofrags(fs, lblkno);
|
||||
ffs_blkfree(ip->i_ump, fs, vp, blkno, fs->fs_bsize, inum, NULL);
|
||||
ffs_blkfree(ip->i_ump, fs, vp, blkno, fs->fs_bsize, inum,
|
||||
vp->v_type, NULL);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@ -1633,7 +1638,7 @@ ffs_snapremove(vp)
|
||||
DIP_SET(ip, i_db[blkno], 0);
|
||||
else if ((dblk == blkstofrags(fs, blkno) &&
|
||||
ffs_snapblkfree(fs, ip->i_devvp, dblk, fs->fs_bsize,
|
||||
ip->i_number, NULL))) {
|
||||
ip->i_number, vp->v_type, NULL))) {
|
||||
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) -
|
||||
btodb(fs->fs_bsize));
|
||||
DIP_SET(ip, i_db[blkno], 0);
|
||||
@ -1658,7 +1663,8 @@ ffs_snapremove(vp)
|
||||
((ufs1_daddr_t *)(ibp->b_data))[loc]= 0;
|
||||
else if ((dblk == blkstofrags(fs, blkno) &&
|
||||
ffs_snapblkfree(fs, ip->i_devvp, dblk,
|
||||
fs->fs_bsize, ip->i_number, NULL))) {
|
||||
fs->fs_bsize, ip->i_number, vp->v_type,
|
||||
NULL))) {
|
||||
ip->i_din1->di_blocks -=
|
||||
btodb(fs->fs_bsize);
|
||||
((ufs1_daddr_t *)(ibp->b_data))[loc]= 0;
|
||||
@ -1672,7 +1678,7 @@ ffs_snapremove(vp)
|
||||
((ufs2_daddr_t *)(ibp->b_data))[loc] = 0;
|
||||
else if ((dblk == blkstofrags(fs, blkno) &&
|
||||
ffs_snapblkfree(fs, ip->i_devvp, dblk,
|
||||
fs->fs_bsize, ip->i_number, NULL))) {
|
||||
fs->fs_bsize, ip->i_number, vp->v_type, NULL))) {
|
||||
ip->i_din2->di_blocks -= btodb(fs->fs_bsize);
|
||||
((ufs2_daddr_t *)(ibp->b_data))[loc] = 0;
|
||||
}
|
||||
@ -1720,12 +1726,13 @@ ffs_snapremove(vp)
|
||||
* must always have been allocated from a BLK_NOCOPY location.
|
||||
*/
|
||||
int
|
||||
ffs_snapblkfree(fs, devvp, bno, size, inum, wkhd)
|
||||
ffs_snapblkfree(fs, devvp, bno, size, inum, vtype, wkhd)
|
||||
struct fs *fs;
|
||||
struct vnode *devvp;
|
||||
ufs2_daddr_t bno;
|
||||
long size;
|
||||
ino_t inum;
|
||||
enum vtype vtype;
|
||||
struct workhead *wkhd;
|
||||
{
|
||||
struct buf *ibp, *cbp, *savedcbp = 0;
|
||||
@ -1874,12 +1881,16 @@ ffs_snapblkfree(fs, devvp, bno, size, inum, wkhd)
|
||||
* simply copy them to the new block. Note that we need
|
||||
* to synchronously write snapshots that have not been
|
||||
* unlinked, and hence will be visible after a crash,
|
||||
* to ensure their integrity.
|
||||
* to ensure their integrity. At a minimum we ensure the
|
||||
* integrity of the filesystem metadata, but use the
|
||||
* dopersistence sysctl-setable flag to decide on the
|
||||
* persistence needed for file content data.
|
||||
*/
|
||||
if (savedcbp != 0) {
|
||||
bcopy(savedcbp->b_data, cbp->b_data, fs->fs_bsize);
|
||||
bawrite(cbp);
|
||||
if (dopersistence && ip->i_effnlink > 0)
|
||||
if ((vtype == VDIR || dopersistence) &&
|
||||
ip->i_effnlink > 0)
|
||||
(void) ffs_syncvnode(vp, MNT_WAIT);
|
||||
continue;
|
||||
}
|
||||
@ -1889,7 +1900,8 @@ ffs_snapblkfree(fs, devvp, bno, size, inum, wkhd)
|
||||
if ((error = readblock(vp, cbp, lbn)) != 0) {
|
||||
bzero(cbp->b_data, fs->fs_bsize);
|
||||
bawrite(cbp);
|
||||
if (dopersistence && ip->i_effnlink > 0)
|
||||
if ((vtype == VDIR || dopersistence) &&
|
||||
ip->i_effnlink > 0)
|
||||
(void) ffs_syncvnode(vp, MNT_WAIT);
|
||||
break;
|
||||
}
|
||||
@ -1898,12 +1910,15 @@ ffs_snapblkfree(fs, devvp, bno, size, inum, wkhd)
|
||||
/*
|
||||
* Note that we need to synchronously write snapshots that
|
||||
* have not been unlinked, and hence will be visible after
|
||||
* a crash, to ensure their integrity.
|
||||
* a crash, to ensure their integrity. At a minimum we
|
||||
* ensure the integrity of the filesystem metadata, but
|
||||
* use the dopersistence sysctl-setable flag to decide on
|
||||
* the persistence needed for file content data.
|
||||
*/
|
||||
if (savedcbp) {
|
||||
vp = savedcbp->b_vp;
|
||||
bawrite(savedcbp);
|
||||
if (dopersistence && VTOI(vp)->i_effnlink > 0)
|
||||
if ((vtype == VDIR || dopersistence) && ip->i_effnlink > 0)
|
||||
(void) ffs_syncvnode(vp, MNT_WAIT);
|
||||
}
|
||||
/*
|
||||
@ -2358,12 +2373,16 @@ ffs_copyonwrite(devvp, bp)
|
||||
* simply copy them to the new block. Note that we need
|
||||
* to synchronously write snapshots that have not been
|
||||
* unlinked, and hence will be visible after a crash,
|
||||
* to ensure their integrity.
|
||||
* to ensure their integrity. At a minimum we ensure the
|
||||
* integrity of the filesystem metadata, but use the
|
||||
* dopersistence sysctl-setable flag to decide on the
|
||||
* persistence needed for file content data.
|
||||
*/
|
||||
if (savedcbp != 0) {
|
||||
bcopy(savedcbp->b_data, cbp->b_data, fs->fs_bsize);
|
||||
bawrite(cbp);
|
||||
if (dopersistence && ip->i_effnlink > 0)
|
||||
if ((devvp == bp->b_vp || bp->b_vp->v_type == VDIR ||
|
||||
dopersistence) && ip->i_effnlink > 0)
|
||||
(void) ffs_syncvnode(vp, MNT_WAIT);
|
||||
else
|
||||
launched_async_io = 1;
|
||||
@ -2375,7 +2394,8 @@ ffs_copyonwrite(devvp, bp)
|
||||
if ((error = readblock(vp, cbp, lbn)) != 0) {
|
||||
bzero(cbp->b_data, fs->fs_bsize);
|
||||
bawrite(cbp);
|
||||
if (dopersistence && ip->i_effnlink > 0)
|
||||
if ((devvp == bp->b_vp || bp->b_vp->v_type == VDIR ||
|
||||
dopersistence) && ip->i_effnlink > 0)
|
||||
(void) ffs_syncvnode(vp, MNT_WAIT);
|
||||
else
|
||||
launched_async_io = 1;
|
||||
@ -2386,12 +2406,16 @@ ffs_copyonwrite(devvp, bp)
|
||||
/*
|
||||
* Note that we need to synchronously write snapshots that
|
||||
* have not been unlinked, and hence will be visible after
|
||||
* a crash, to ensure their integrity.
|
||||
* a crash, to ensure their integrity. At a minimum we
|
||||
* ensure the integrity of the filesystem metadata, but
|
||||
* use the dopersistence sysctl-setable flag to decide on
|
||||
* the persistence needed for file content data.
|
||||
*/
|
||||
if (savedcbp) {
|
||||
vp = savedcbp->b_vp;
|
||||
bawrite(savedcbp);
|
||||
if (dopersistence && VTOI(vp)->i_effnlink > 0)
|
||||
if ((devvp == bp->b_vp || bp->b_vp->v_type == VDIR ||
|
||||
dopersistence) && VTOI(vp)->i_effnlink > 0)
|
||||
(void) ffs_syncvnode(vp, MNT_WAIT);
|
||||
else
|
||||
launched_async_io = 1;
|
||||
|
@ -5172,6 +5172,7 @@ newfreefrag(ip, blkno, size, lbn)
|
||||
freefrag->ff_state = ATTACHED;
|
||||
LIST_INIT(&freefrag->ff_jwork);
|
||||
freefrag->ff_inum = ip->i_number;
|
||||
freefrag->ff_vtype = ITOV(ip)->v_type;
|
||||
freefrag->ff_blkno = blkno;
|
||||
freefrag->ff_fragsize = size;
|
||||
|
||||
@ -5216,7 +5217,7 @@ handle_workitem_freefrag(freefrag)
|
||||
}
|
||||
FREE_LOCK(&lk);
|
||||
ffs_blkfree(ump, ump->um_fs, ump->um_devvp, freefrag->ff_blkno,
|
||||
freefrag->ff_fragsize, freefrag->ff_inum, &wkhd);
|
||||
freefrag->ff_fragsize, freefrag->ff_inum, freefrag->ff_vtype, &wkhd);
|
||||
ACQUIRE_LOCK(&lk);
|
||||
WORKITEM_FREE(freefrag, D_FREEFRAG);
|
||||
FREE_LOCK(&lk);
|
||||
@ -5724,6 +5725,7 @@ newfreeblks(mp, ip)
|
||||
freeblks->fb_state = ATTACHED;
|
||||
freeblks->fb_uid = ip->i_uid;
|
||||
freeblks->fb_inum = ip->i_number;
|
||||
freeblks->fb_vtype = ITOV(ip)->v_type;
|
||||
freeblks->fb_modrev = DIP(ip, i_modrev);
|
||||
freeblks->fb_devvp = ip->i_devvp;
|
||||
freeblks->fb_chkcnt = 0;
|
||||
@ -7263,7 +7265,7 @@ freework_freeblock(freework)
|
||||
freeblks->fb_freecnt += btodb(bsize);
|
||||
FREE_LOCK(&lk);
|
||||
ffs_blkfree(ump, fs, freeblks->fb_devvp, freework->fw_blkno, bsize,
|
||||
freeblks->fb_inum, &wkhd);
|
||||
freeblks->fb_inum, freeblks->fb_vtype, &wkhd);
|
||||
ACQUIRE_LOCK(&lk);
|
||||
/*
|
||||
* The jnewblk will be discarded and the bits in the map never
|
||||
@ -7669,7 +7671,8 @@ indir_trunc(freework, dbn, lbn)
|
||||
freedeps++;
|
||||
}
|
||||
ffs_blkfree(ump, fs, freeblks->fb_devvp, nb,
|
||||
fs->fs_bsize, freeblks->fb_inum, &wkhd);
|
||||
fs->fs_bsize, freeblks->fb_inum,
|
||||
freeblks->fb_vtype, &wkhd);
|
||||
}
|
||||
}
|
||||
if (goingaway) {
|
||||
@ -7702,7 +7705,7 @@ indir_trunc(freework, dbn, lbn)
|
||||
fs_pendingblocks += nblocks;
|
||||
dbn = dbtofsb(fs, dbn);
|
||||
ffs_blkfree(ump, fs, freeblks->fb_devvp, dbn, fs->fs_bsize,
|
||||
freeblks->fb_inum, NULL);
|
||||
freeblks->fb_inum, freeblks->fb_vtype, NULL);
|
||||
/* Non SUJ softdep does single-threaded truncations. */
|
||||
freeblks->fb_freecnt += fs_pendingblocks;
|
||||
if (freework->fw_blkno == dbn) {
|
||||
|
@ -511,6 +511,7 @@ struct freefrag {
|
||||
ufs2_daddr_t ff_blkno; /* fragment physical block number */
|
||||
long ff_fragsize; /* size of fragment being deleted */
|
||||
ino_t ff_inum; /* owning inode number */
|
||||
enum vtype ff_vtype; /* owning inode's file type */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -538,6 +539,7 @@ struct freeblks {
|
||||
ufs2_daddr_t fb_chkcnt; /* Expected blks released. */
|
||||
ufs2_daddr_t fb_freecnt; /* Actual blocks released. */
|
||||
ino_t fb_inum; /* inode owner of blocks */
|
||||
enum vtype fb_vtype; /* inode owner's file type */
|
||||
uid_t fb_uid; /* uid of previous owner of blocks */
|
||||
int fb_ref; /* Children outstanding. */
|
||||
int fb_cgwait; /* cg writes outstanding. */
|
||||
|
32
tools/regression/bin/sh/builtins/case8.0
Normal file
32
tools/regression/bin/sh/builtins/case8.0
Normal file
@ -0,0 +1,32 @@
|
||||
# $FreeBSD$
|
||||
|
||||
case aZ_ in
|
||||
[[:alpha:]_][[:upper:]_][[:alpha:]_]) ;;
|
||||
*) echo Failed at $LINENO ;;
|
||||
esac
|
||||
|
||||
case ' ' in
|
||||
[[:alpha:][:digit:]]) echo Failed at $LINENO ;;
|
||||
[![:alpha:][:digit:]]) ;;
|
||||
*) echo Failed at $LINENO ;;
|
||||
esac
|
||||
|
||||
case '.X.' in
|
||||
*[[:lower:]]*) echo Failed at $LINENO ;;
|
||||
*[[:upper:]]*) ;;
|
||||
*) echo Failed at $LINENO ;;
|
||||
esac
|
||||
|
||||
case ' ' in
|
||||
[![:print:]]) echo Failed at $LINENO ;;
|
||||
[![:alnum:][:punct:]]) ;;
|
||||
*) echo Failed at $LINENO ;;
|
||||
esac
|
||||
|
||||
case '
|
||||
' in
|
||||
[[:print:]]) echo Failed at $LINENO ;;
|
||||
['
|
||||
'[:digit:]]) ;;
|
||||
*) echo Failed at $LINENO ;;
|
||||
esac
|
@ -840,8 +840,8 @@ help(int argc, char *argv[])
|
||||
printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help);
|
||||
|
||||
printf("\n[-] : You shouldn't use these ones anymore.\n");
|
||||
printf("[*] : RFC2834 options support required.\n");
|
||||
printf("[**] : Non-standard RFC2834 option.\n");
|
||||
printf("[*] : RFC2347 options support required.\n");
|
||||
printf("[**] : Non-standard RFC2347 option.\n");
|
||||
return;
|
||||
}
|
||||
while (--argc > 0) {
|
||||
|
@ -174,7 +174,7 @@ The
|
||||
.Nm
|
||||
command appeared in
|
||||
.Bx 4.3 .
|
||||
.Sh BUGS
|
||||
.Sh NOTES
|
||||
Because there is no user-login or validation within
|
||||
the
|
||||
.Tn TFTP
|
||||
@ -185,4 +185,5 @@ exact methods are specific to each site and therefore
|
||||
difficult to document here.
|
||||
.Pp
|
||||
Files larger than 33488896 octets (65535 blocks) cannot be transferred
|
||||
without client and server supporting blocksize negotiation (RFC1783).
|
||||
without client and server supporting the TFTP blocksize option (RFC2348),
|
||||
or the non-standard TFTP rollover option.
|
||||
|
@ -163,7 +163,7 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
* If we'll need to use it or we're updating it,
|
||||
* then create the base home directory if necessary
|
||||
*/
|
||||
if (arg != NULL || getarg(args, 'm') != NULL) {
|
||||
if ((arg != NULL || getarg(args, 'm') != NULL) && (getarg(args, 'd') == NULL)) {
|
||||
int l = strlen(cnf->home);
|
||||
|
||||
if (l > 1 && cnf->home[l-1] == '/') /* Shave off any trailing path delimiter */
|
||||
|
Loading…
Reference in New Issue
Block a user