When a socket is not connected, allow the peer "struct sockaddr"

to be included in the meta information that is associated with
incoming and outgoing packets.

Reviewed by:	julian
MFC after:	1 week
This commit is contained in:
Archie Cobbs 2001-11-28 19:39:58 +00:00
parent d23c1cd5d7
commit 19ff9e5f3e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=87070
2 changed files with 77 additions and 13 deletions

View File

@ -885,12 +885,38 @@ ng_ksocket_rcvdata(hook_p hook, item_p item)
const node_p node = NG_HOOK_NODE(hook);
const priv_p priv = NG_NODE_PRIVATE(node);
struct socket *const so = priv->so;
struct sockaddr *sa = NULL;
meta_p meta;
int error;
struct mbuf *m;
/* Extract data and meta information */
NGI_GET_M(item, m);
NGI_GET_META(item, meta);
NG_FREE_ITEM(item);
error = (*so->so_proto->pr_usrreqs->pru_sosend)(so, 0, 0, m, 0, 0, td);
/* If any meta info, look for peer socket address */
if (meta != NULL) {
struct meta_field_header *field;
/* Look for peer socket address */
for (field = &meta->options[0];
(caddr_t)field < (caddr_t)meta + meta->used_len;
field = (struct meta_field_header *)
((caddr_t)field + field->len)) {
if (field->cookie != NGM_KSOCKET_COOKIE
|| field->type != NG_KSOCKET_META_SOCKADDR)
continue;
sa = (struct sockaddr *)field->data;
break;
}
}
/* Send packet */
error = (*so->so_proto->pr_usrreqs->pru_sosend)(so, sa, 0, m, 0, 0, td);
/* Clean up and exit */
NG_FREE_META(meta);
return (error);
}
@ -1056,20 +1082,55 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag)
auio.uio_td = NULL;
auio.uio_resid = 1000000000;
flags = MSG_DONTWAIT;
do {
if ((error = (*so->so_proto->pr_usrreqs->pru_soreceive)
(so, (struct sockaddr **)0, &auio, &m,
(struct mbuf **)0, &flags)) == 0
&& m != NULL) {
struct mbuf *n;
while (1) {
struct sockaddr *sa = NULL;
meta_p meta = NULL;
struct mbuf *n;
/* Don't trust the various socket layers to get the
packet header and length correct (eg. kern/15175) */
for (n = m, m->m_pkthdr.len = 0; n; n = n->m_next)
m->m_pkthdr.len += n->m_len;
NG_SEND_DATA_ONLY(error, priv->hook, m);
/* Try to get next packet from socket */
if ((error = (*so->so_proto->pr_usrreqs->pru_soreceive)
(so, (so->so_state & SS_ISCONNECTED) ? NULL : &sa,
&auio, &m, (struct mbuf **)0, &flags)) != 0)
break;
/* See if we got anything */
if (m == NULL) {
if (sa != NULL)
FREE(sa, M_SONAME);
break;
}
} while (error == 0 && m != NULL);
/* Don't trust the various socket layers to get the
packet header and length correct (eg. kern/15175) */
for (n = m, m->m_pkthdr.len = 0; n != NULL; n = n->m_next)
m->m_pkthdr.len += n->m_len;
/* Put peer's socket address (if any) into a meta info blob */
if (sa != NULL) {
struct meta_field_header *mhead;
u_int len;
len = sizeof(*meta) + sizeof(*mhead) + sa->sa_len;
MALLOC(meta, meta_p, len, M_NETGRAPH_META, M_NOWAIT);
if (meta == NULL) {
FREE(sa, M_SONAME);
goto sendit;
}
mhead = &meta->options[0];
bzero(meta, sizeof(*meta));
bzero(mhead, sizeof(*mhead));
meta->allocated_len = len;
meta->used_len = len;
mhead->cookie = NGM_KSOCKET_COOKIE;
mhead->type = NG_KSOCKET_META_SOCKADDR;
mhead->len = sizeof(*mhead) + sa->sa_len;
bcopy(sa, mhead->data, sa->sa_len);
FREE(sa, M_SONAME);
}
sendit: /* Forward data with optional peer sockaddr as meta info */
NG_SEND_DATA(error, priv->hook, m, meta);
}
/*
* If the peer has closed the connection, forward a 0-length mbuf

View File

@ -98,4 +98,7 @@ enum {
NGM_KSOCKET_GETOPT,
};
/* Meta information ID's */
#define NG_KSOCKET_META_SOCKADDR 1 /* data is struct sockaddr */
#endif /* _NETGRAPH_KSOCKET_H_ */