| version 1.175, 2008/10/11 16:39:07 |
version 1.176, 2008/10/12 09:26:50 |
| Line 1851 sogetopt(struct socket *so, struct socko |
|
| Line 1851 sogetopt(struct socket *so, struct socko |
|
| * alloc sockopt data buffer buffer |
* alloc sockopt data buffer buffer |
| * - will be released at destroy |
* - will be released at destroy |
| */ |
*/ |
| static void |
static int |
| sockopt_alloc(struct sockopt *sopt, size_t len) |
sockopt_alloc(struct sockopt *sopt, size_t len, km_flag_t kmflag) |
| { |
{ |
| |
|
| KASSERT(sopt->sopt_size == 0); |
KASSERT(sopt->sopt_size == 0); |
| |
|
| if (len > sizeof(sopt->sopt_buf)) |
if (len > sizeof(sopt->sopt_buf)) { |
| sopt->sopt_data = kmem_zalloc(len, KM_SLEEP); |
sopt->sopt_data = kmem_zalloc(len, kmflag); |
| else |
if (sopt->sopt_data == NULL) |
| |
return ENOMEM; |
| |
} else |
| sopt->sopt_data = sopt->sopt_buf; |
sopt->sopt_data = sopt->sopt_buf; |
| |
|
| sopt->sopt_size = len; |
sopt->sopt_size = len; |
| |
return 0; |
| } |
} |
| |
|
| /* |
/* |
| * initialise sockopt storage |
* initialise sockopt storage |
| |
* - MAY sleep during allocation |
| */ |
*/ |
| void |
void |
| sockopt_init(struct sockopt *sopt, int level, int name, size_t size) |
sockopt_init(struct sockopt *sopt, int level, int name, size_t size) |
| Line 1876 sockopt_init(struct sockopt *sopt, int l |
|
| Line 1880 sockopt_init(struct sockopt *sopt, int l |
|
| |
|
| sopt->sopt_level = level; |
sopt->sopt_level = level; |
| sopt->sopt_name = name; |
sopt->sopt_name = name; |
| sockopt_alloc(sopt, size); |
(void)sockopt_alloc(sopt, size, KM_SLEEP); |
| } |
} |
| |
|
| /* |
/* |
| Line 1896 sockopt_destroy(struct sockopt *sopt) |
|
| Line 1900 sockopt_destroy(struct sockopt *sopt) |
|
| /* |
/* |
| * set sockopt value |
* set sockopt value |
| * - value is copied into sockopt |
* - value is copied into sockopt |
| * - memory is allocated when necessary |
* - memory is allocated when necessary, will not sleep |
| */ |
*/ |
| int |
int |
| sockopt_set(struct sockopt *sopt, const void *buf, size_t len) |
sockopt_set(struct sockopt *sopt, const void *buf, size_t len) |
| { |
{ |
| |
int error; |
| |
|
| if (sopt->sopt_size == 0) |
if (sopt->sopt_size == 0) { |
| sockopt_alloc(sopt, len); |
error = sockopt_alloc(sopt, len, KM_NOSLEEP); |
| |
if (error) |
| |
return error; |
| |
} |
| |
|
| KASSERT(sopt->sopt_size == len); |
KASSERT(sopt->sopt_size == len); |
| memcpy(sopt->sopt_data, buf, len); |
memcpy(sopt->sopt_data, buf, len); |
| Line 1949 sockopt_getint(const struct sockopt *sop |
|
| Line 1957 sockopt_getint(const struct sockopt *sop |
|
| * set sockopt value from mbuf |
* set sockopt value from mbuf |
| * - ONLY for legacy code |
* - ONLY for legacy code |
| * - mbuf is released by sockopt |
* - mbuf is released by sockopt |
| |
* - will not sleep |
| */ |
*/ |
| int |
int |
| sockopt_setmbuf(struct sockopt *sopt, struct mbuf *m) |
sockopt_setmbuf(struct sockopt *sopt, struct mbuf *m) |
| { |
{ |
| size_t len; |
size_t len; |
| |
int error; |
| |
|
| len = m_length(m); |
len = m_length(m); |
| |
|
| if (sopt->sopt_size == 0) |
if (sopt->sopt_size == 0) { |
| sockopt_alloc(sopt, len); |
error = sockopt_alloc(sopt, len, KM_NOSLEEP); |
| |
if (error) |
| |
return error; |
| |
} |
| |
|
| KASSERT(sopt->sopt_size == len); |
KASSERT(sopt->sopt_size == len); |
| m_copydata(m, 0, len, sopt->sopt_data); |
m_copydata(m, 0, len, sopt->sopt_data); |
| Line 1971 sockopt_setmbuf(struct sockopt *sopt, st |
|
| Line 1984 sockopt_setmbuf(struct sockopt *sopt, st |
|
| * get sockopt value into mbuf |
* get sockopt value into mbuf |
| * - ONLY for legacy code |
* - ONLY for legacy code |
| * - mbuf to be released by the caller |
* - mbuf to be released by the caller |
| |
* - will not sleep |
| */ |
*/ |
| struct mbuf * |
struct mbuf * |
| sockopt_getmbuf(const struct sockopt *sopt) |
sockopt_getmbuf(const struct sockopt *sopt) |
| { |
{ |
| struct mbuf *m; |
struct mbuf *m; |
| |
|
| m = m_get(M_WAIT, MT_SOOPTS); |
if (sopt->sopt_size > MCLBYTES) |
| if (m == NULL) |
|
| return NULL; |
return NULL; |
| |
|
| m->m_len = MLEN; |
m = m_get(M_DONTWAIT, MT_SOOPTS); |
| m_copyback(m, 0, sopt->sopt_size, sopt->sopt_data); |
if (m == NULL) |
| if (m_length(m) != max(sopt->sopt_size, MLEN)) { |
|
| m_freem(m); |
|
| return NULL; |
return NULL; |
| |
|
| |
if (sopt->sopt_size > MLEN) { |
| |
MCLGET(m, M_DONTWAIT); |
| |
if ((m->m_flags & M_EXT) == 0) { |
| |
m_free(m); |
| |
return NULL; |
| |
} |
| } |
} |
| m->m_len = min(sopt->sopt_size, MLEN); |
|
| |
memcpy(mtod(m, void *), sopt->sopt_data, sopt->sopt_size); |
| |
m->m_len = sopt->sopt_size; |
| |
|
| return m; |
return m; |
| } |
} |