51#include <sys/kernel.h>
54#include <sys/malloc.h>
56#include <sys/protosw.h>
58#include <sys/socket.h>
59#include <sys/socketvar.h>
68#include <netinet/in.h>
69#include <netinet/ip.h>
71#ifdef NG_SEPARATE_MALLOC
73 "netgraph ksock node");
75#define M_NETGRAPH_KSOCKET M_NETGRAPH
78#define OFFSETOF(s, e) ((char *)&((s *)0)->e - (char *)((s *)0))
79#define SADATA_OFFSET (OFFSETOF(struct sockaddr, sa_data))
90 u_int32_t response_token;
96#define KSF_CONNECTING 0x00000001
97#define KSF_ACCEPTING 0x00000002
98#define KSF_EOFSEEN 0x00000004
99#define KSF_CLONED 0x00000008
100#define KSF_EMBRYONIC 0x00000010
120 {
"local", PF_LOCAL },
122 {
"inet6", PF_INET6 },
129 {
"stream", SOCK_STREAM },
130 {
"dgram", SOCK_DGRAM },
133 {
"seqpacket", SOCK_SEQPACKET },
139 {
"ip", IPPROTO_IP, PF_INET },
140 {
"raw", IPPROTO_RAW, PF_INET },
141 {
"icmp", IPPROTO_ICMP, PF_INET },
142 {
"igmp", IPPROTO_IGMP, PF_INET },
143 {
"tcp", IPPROTO_TCP, PF_INET },
144 {
"udp", IPPROTO_UDP, PF_INET },
145 {
"gre", IPPROTO_GRE, PF_INET },
146 {
"esp", IPPROTO_ESP, PF_INET },
147 {
"ah", IPPROTO_AH, PF_INET },
148 {
"swipe", IPPROTO_SWIPE, PF_INET },
149 {
"encap", IPPROTO_ENCAP, PF_INET },
150 {
"divert", IPPROTO_DIVERT, PF_INET },
151 {
"pim", IPPROTO_PIM, PF_INET },
159 const char *s,
int family);
161 void *arg1,
int arg2);
170 const u_char *start,
const u_char *buf)
172 const struct sockaddr *sa;
202 const char *s,
int *off,
const u_char *
const start,
203 u_char *
const buf,
int *buflen)
205 struct sockaddr *
const sa = (
struct sockaddr *)buf;
215 s, off, start, buf, buflen);
219 while (isspace(s[*off]))
221 if ((t = strchr(s + *off,
'/')) == NULL)
223 if ((len = t - (s + *off)) >
sizeof(fambuf) - 1)
225 strncpy(fambuf, s + *off, len);
234 sa->sa_family = family;
237 switch (sa->sa_family) {
240 const int pathoff =
OFFSETOF(
struct sockaddr_un, sun_path);
241 struct sockaddr_un *
const sun = (
struct sockaddr_un *)sa;
247 pathlen = strlen(path);
248 if (pathlen > SOCK_MAXADDRLEN) {
252 if (*buflen < pathoff + pathlen) {
257 bcopy(path, sun->sun_path, pathlen);
258 sun->sun_len = pathoff + pathlen;
265 struct sockaddr_in *
const sin = (
struct sockaddr_in *)sa;
269 for (i = 0; i < 4; i++) {
273 val = strtoul(s + *off, &eptr, 10);
274 if (val > 0xff || eptr == s + *off)
276 *off += (eptr - (s + *off));
277 ((u_char *)&sin->sin_addr)[i] = (u_char)val;
282 }
else if (s[*off] ==
':') {
284 val = strtoul(s + *off, &eptr, 10);
285 if (val > 0xffff || eptr == s + *off)
287 *off += (eptr - (s + *off));
288 sin->sin_port = htons(val);
292 bzero(&sin->sin_zero,
sizeof(sin->sin_zero));
293 sin->sin_len =
sizeof(*sin);
306 *buflen = sa->sa_len;
313 const u_char *
data,
int *off,
char *cbuf,
int cbuflen)
315 const struct sockaddr *sa = (
const struct sockaddr *)(
data + *off);
319 switch (sa->sa_family) {
322 const int pathoff =
OFFSETOF(
struct sockaddr_un, sun_path);
323 const struct sockaddr_un *sun = (
const struct sockaddr_un *)sa;
324 const int pathlen = sun->sun_len - pathoff;
325 char pathbuf[SOCK_MAXADDRLEN + 1];
328 bcopy(sun->sun_path, pathbuf, pathlen);
331 slen += snprintf(cbuf, cbuflen,
"local/%s", pathtoken);
335 *off += sun->sun_len;
341 const struct sockaddr_in *sin = (
const struct sockaddr_in *)sa;
343 slen += snprintf(cbuf, cbuflen,
"inet/%d.%d.%d.%d",
344 ((
const u_char *)&sin->sin_addr)[0],
345 ((
const u_char *)&sin->sin_addr)[1],
346 ((
const u_char *)&sin->sin_addr)[2],
347 ((
const u_char *)&sin->sin_addr)[3]);
348 if (sin->sin_port != 0) {
349 slen += snprintf(cbuf + strlen(cbuf),
350 cbuflen - strlen(cbuf),
":%d",
351 (u_int)ntohs(sin->sin_port));
355 *off +=
sizeof(*sin);
366 data, off, cbuf, cbuflen);
389 const u_char *start,
const u_char *buf)
396 msg = (
const struct ng_mesg *)((
const u_char *)sopt -
sizeof(*msg));
501#define ERROUT(x) do { error = (x); goto done; } while (0)
522 LIST_INIT(&
priv->embryos);
542 struct thread *td = curthread;
545 int family,
type, protocol, error;
548 if (
priv->hook != NULL)
554 LIST_REMOVE(
priv, siblings);
555 priv->flags &= ~KSF_EMBRYONIC;
559 snprintf(
name,
sizeof(
name),
"%s", name0);
561 if ((s2 = strchr(s1,
'/')) == NULL)
568 if ((s2 = strchr(s1,
'/')) == NULL)
580 error = socreate(family, &
priv->so,
type, protocol,
606 struct socket *
const so =
priv->so;
609 SOCKBUF_LOCK(&
priv->so->so_rcv);
611 SOCKBUF_UNLOCK(&
priv->so->so_rcv);
612 SOCKBUF_LOCK(&
priv->so->so_snd);
614 SOCKBUF_UNLOCK(&
priv->so->so_snd);
616 priv->so->so_state |= SS_NBIO;
617 SOCK_UNLOCK(
priv->so);
662 struct thread *td = curthread;
664 struct socket *
const so =
priv->so;
676 struct sockaddr *
const sa
677 = (
struct sockaddr *)msg->
data;
687 error = sobind(so, sa, td);
699 so->so_state |= SS_NBIO;
700 error = solisten(so, *((int32_t *)msg->
data), td);
713 if (!(so->so_options & SO_ACCEPTCONN))
724 if (error != 0 && error != EWOULDBLOCK)
733 struct sockaddr *
const sa
734 = (
struct sockaddr *)msg->
data;
744 if ((so->so_state & SS_ISCONNECTING) != 0)
746 if ((error = soconnect(so, sa, td)) != 0) {
747 so->so_state &= ~SS_ISCONNECTING;
750 if ((so->so_state & SS_ISCONNECTING) != 0) {
763 int (*func)(
struct socket *so,
struct sockaddr **nam);
764 struct sockaddr *sa = NULL;
776 & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
778 func = so->so_proto->pr_usrreqs->pru_peeraddr;
780 func = so->so_proto->pr_usrreqs->pru_sockaddr;
783 if ((error = (*func)(so, &sa)) != 0)
785 len = (sa == NULL) ? 0 : sa->sa_len;
793 bcopy(sa, resp->
data, len);
821 sopt.sopt_dir = SOPT_GET;
822 sopt.sopt_level = ksopt->
level;
823 sopt.sopt_name = ksopt->
name;
827 sopt.sopt_val = ksopt->
value;
828 if ((error = sogetopt(so, &sopt)) != 0) {
843 const int valsize = msg->
header.
arglen -
sizeof(*ksopt);
853 sopt.sopt_dir = SOPT_SET;
854 sopt.sopt_level = ksopt->
level;
855 sopt.sopt_name = ksopt->
name;
856 sopt.sopt_val = ksopt->
value;
857 sopt.sopt_valsize = valsize;
859 error = sosetopt(so, &sopt);
884 struct thread *td = curthread;
887 struct socket *
const so =
priv->so;
888 struct sockaddr *sa = NULL;
891#ifdef ALIGNED_POINTER
899#ifdef ALIGNED_POINTER
900 if (!ALIGNED_POINTER(mtod(m, caddr_t), uint32_t)) {
901 n = m_defrag(m, M_NOWAIT);
920 m->m_flags &= ~(M_BCAST|M_MCAST);
923 error = sosend(so,
sa, 0, m, 0, 0, td);
938 if (
priv->so != NULL) {
939 SOCKBUF_LOCK(&
priv->so->so_rcv);
940 soupcall_clear(
priv->so, SO_RCV);
941 SOCKBUF_UNLOCK(&
priv->so->so_rcv);
942 SOCKBUF_LOCK(&
priv->so->so_snd);
943 soupcall_clear(
priv->so, SO_SND);
944 SOCKBUF_UNLOCK(&
priv->so->so_snd);
951 LIST_REMOVE(
priv, siblings);
952 priv->flags &= ~KSF_EMBRYONIC;
956 while (!LIST_EMPTY(&
priv->embryos)) {
957 embryo = LIST_FIRST(&
priv->embryos);
976 (
"%s: numhooks=%d?", __func__,
1011 if (atomic_cmpset_int(&
priv->fn_sent, 0, 1) &&
1013 atomic_store_rel_int(&
priv->fn_sent, 0);
1028 struct socket *so = arg1;
1033 KASSERT(so ==
priv->so, (
"%s: wrong socket", __func__));
1036 atomic_store_rel_int(&
priv->fn_sent, 0);
1040 if ((error = so->so_error) != 0) {
1042 so->so_state &= ~SS_ISCONNECTING;
1044 if (!(so->so_state & SS_ISCONNECTING)) {
1047 if (response != NULL) {
1050 *(int32_t *)response->
data = error;
1057 response,
priv->response_addr, 0);
1059 priv->flags &= ~KSF_CONNECTING;
1072 if (
priv->hook == NULL)
1078 struct sockaddr *sa;
1084 uio.uio_resid = IP_MAXPACKET;
1085 flags = MSG_DONTWAIT;
1087 if ((error = soreceive(so, (so->so_state & SS_ISCONNECTED) ?
1088 NULL : &sa, &uio, &m, NULL, &
flags)) != 0)
1092 if (
flags & MSG_TRUNC) {
1102 KASSERT(m->m_nextpkt == NULL, (
"%s: nextpkt", __func__));
1109 if (so->so_type == SOCK_STREAM) {
1112 mh = m_gethdr(M_NOWAIT, MT_DATA);
1121 for (; m; m = m->m_next)
1122 mh->m_pkthdr.len += m->m_len;
1132 sa->sa_len, M_NOWAIT);
1137 bcopy(
sa, &stag->
sa,
sa->sa_len);
1140 m_tag_prepend(m, &stag->
tag);
1151 if (so->so_rcv.sb_state & SBS_CANTRCVMORE &&
1155 m = m_gethdr(M_NOWAIT, MT_DATA);
1165 struct socket *
const head =
priv->so;
1167 struct sockaddr *sa = NULL;
1175 SOLISTEN_LOCK(head);
1176 error = solisten_dequeue(head, &so, SOCK_NONBLOCK);
1177 if (error == EWOULDBLOCK) {
1181 priv->flags &= ~KSF_ACCEPTING;
1185 if ((error = soaccept(so, &sa)) != 0)
1204 free(resp, M_NETGRAPH);
1211 free(resp, M_NETGRAPH);
1226 LIST_INSERT_HEAD(&
priv->embryos, priv2, siblings);
1228 SOCKBUF_LOCK(&so->so_rcv);
1230 SOCKBUF_UNLOCK(&so->so_rcv);
1231 SOCKBUF_LOCK(&so->so_snd);
1233 SOCKBUF_UNLOCK(&so->so_snd);
1239 bcopy(sa, &resp_data->
addr, sa->sa_len);
1254 const char *s,
int family)
1260 for (k = 0; aliases[k].
name != NULL; k++) {
1261 if (strcmp(s, aliases[k].
name) == 0
1262 && aliases[k].family == family)
1263 return aliases[k].
value;
1267 val = (int)strtoul(s, &eptr, 10);
1268 if (val < 0 || *eptr !=
'\0')
int ng_connect_t(hook_p hook)
#define NG_HOOK_NODE(hook)
int ng_rcvmsg_t(node_p node, item_p item, hook_p lasthook)
int ng_disconnect_t(hook_p hook)
#define NG_NODE_SET_PRIVATE(node, val)
#define NG_RESPOND_MSG(error, here, item, resp)
#define NG_NODE_IS_VALID(node)
#define NG_NODE_UNREF(node)
int ng_rmnode_self(node_p here)
int ng_send_fn1(node_p node, hook_p hook, ng_item_fn *fn, void *arg1, int arg2, int flags)
#define NG_SEND_DATA_ONLY(error, hook, m)
#define NG_SEND_MSG_ID(error, here, msg, ID, retaddr)
#define NG_HOOK_FORCE_QUEUE(hook)
int ng_rcvdata_t(hook_p hook, item_p item)
int ng_shutdown_t(node_p node)
#define NG_FREE_ITEM(item)
int ng_make_node_common(struct ng_type *typep, node_p *nodep)
int ng_constructor_t(node_p node)
int ng_send_fn(node_p node, hook_p hook, ng_item_fn *fn, void *arg1, int arg2)
#define NG_NODE_NUMHOOKS(node)
#define NGI_GET_MSG(i, m)
#define NG_NODE_PRIVATE(node)
int ng_newhook_t(node_p node, hook_p hook, const char *name)
MALLOC_DEFINE(M_NG_CCATM, "ng_ccatm", "netgraph uni api node")
static const struct ng_ksocket_alias ng_ksocket_protos[]
static const struct ng_parse_type ng_ksocket_generic_sockaddr_type
struct ng_ksocket_private * priv_p
static int ng_parse_generic_sockdata_getLength(const struct ng_parse_type *type, const u_char *start, const u_char *buf)
static const struct ng_parse_type ng_ksocket_sockopt_type
NETGRAPH_INIT(ksocket, &ng_ksocket_typestruct)
static const struct ng_parse_type ng_ksocket_sockaddr_type
static const struct ng_parse_type ng_ksocket_accept_type
static const struct ng_parse_struct_field ng_ksocket_accept_type_fields[]
static const struct ng_parse_struct_field ng_ksocket_sockopt_type_fields[]
static void ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int arg2)
static int ng_ksocket_parse(const struct ng_ksocket_alias *aliases, const char *s, int family)
static struct ng_type ng_ksocket_typestruct
static ng_connect_t ng_ksocket_connect
static int ng_ksocket_incoming(struct socket *so, void *arg, int waitflag)
static int ng_parse_sockoptval_getLength(const struct ng_parse_type *type, const u_char *start, const u_char *buf)
static const struct ng_parse_type ng_ksocket_generic_sockdata_type
static const struct ng_cmdlist ng_ksocket_cmds[]
#define M_NETGRAPH_KSOCKET
static const struct ng_parse_type ng_ksocket_sockoptval_type
static const struct ng_parse_struct_field ng_parse_generic_sockaddr_type_fields[]
static ng_shutdown_t ng_ksocket_shutdown
static const struct ng_ksocket_alias ng_ksocket_types[]
static int ng_ksocket_accept(priv_p)
static ng_constructor_t ng_ksocket_constructor
static ng_disconnect_t ng_ksocket_disconnect
static int ng_ksocket_sockaddr_parse(const struct ng_parse_type *type, const char *s, int *off, const u_char *const start, u_char *const buf, int *buflen)
static const struct ng_ksocket_alias ng_ksocket_families[]
static ng_rcvdata_t ng_ksocket_rcvdata
static ng_rcvmsg_t ng_ksocket_rcvmsg
static ng_newhook_t ng_ksocket_newhook
static int ng_ksocket_sockaddr_unparse(const struct ng_parse_type *type, const u_char *data, int *off, char *cbuf, int cbuflen)
@ NGM_KSOCKET_GETPEERNAME
#define NGM_KSOCKET_COOKIE
#define NGM_KSOCKET_ACCEPT_INFO
#define NG_KSOCKET_TAG_SOCKADDR
#define NG_KSOCKET_NODE_TYPE
#define NG_KSOCKET_MAX_OPTLEN
#define NG_KSOCKET_SOCKOPT_INFO(svtype)
#define NG_MKRESPONSE(rsp, msg, len, how)
#define NG_MKMESSAGE(msg, cookie, cmdid, len, how)
const struct ng_parse_type ng_parse_int32_type
char * ng_get_string_token(const char *s, int *startp, int *lenp, int *slenp)
const struct ng_parse_type ng_parse_bytearray_type
const struct ng_parse_type ng_parse_struct_type
const struct ng_parse_type ng_parse_uint8_type
char * ng_encode_string(const char *raw, int slen)
enum ng_parse_token ng_parse_get_token(const char *s, int *startp, int *lenp)
static LIST_HEAD(ngatm_msg)
struct ng_mesg::ng_msghdr header
const struct ng_parse_type * supertype