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