This commit is contained in:
Attilio Rao 2011-06-16 07:16:02 +00:00
commit dbab0763f9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/largeSMP/; revision=223140
35 changed files with 2410 additions and 739 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -15,7 +15,7 @@ NO_PIC=
INCS= stand.h
MAN= libstand.3
WARNS?= 0
WARNS?= 2
CFLAGS+= -ffreestanding -Wformat
CFLAGS+= -I${.CURDIR}

View File

@ -100,7 +100,7 @@ sendrecv(struct iodesc *d,
cc, ssize);
tleft = tmo;
tmo <<= 1;
tmo += MINTMO;
if (tmo > MAXTMO)
tmo = MAXTMO;

View File

@ -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
}

View File

@ -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).

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);
}

View File

@ -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;
/*-

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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) {

View File

@ -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. */

View 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

View File

@ -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) {

View File

@ -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.

View File

@ -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 */