diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2004-11-26 18:02:23 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2004-11-26 18:02:23 +0000 |
commit | 8f40035a88fee575709a5aa28fed7b098e3854ad (patch) | |
tree | 816dfaca9c54081f903259c49e6e334e226fb001 /sys/net/pfkeyv2.c | |
parent | db3cb2196dc4401149258da8e6829cd3dad178e7 (diff) |
implement net.key.v2.sadb_dump.{unspec,esp,ah,...} sysctl subtree
and use sysctl for 'ipsecadm show'; ok deraadt
Diffstat (limited to 'sys/net/pfkeyv2.c')
-rw-r--r-- | sys/net/pfkeyv2.c | 111 |
1 files changed, 107 insertions, 4 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c index 136d75c7994..1e6b8a75395 100644 --- a/sys/net/pfkeyv2.c +++ b/sys/net/pfkeyv2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.c,v 1.93 2004/11/19 10:11:52 hshoexer Exp $ */ +/* $OpenBSD: pfkeyv2.c,v 1.94 2004/11/26 18:02:22 markus Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 @@ -493,7 +493,7 @@ ret: * Get all the information contained in an SA to a PFKEYV2 message. */ int -pfkeyv2_get(struct tdb *sa, void **headers, void **buffer) +pfkeyv2_get(struct tdb *sa, void **headers, void **buffer, int *lenp) { int rval, i; void *p; @@ -550,6 +550,14 @@ pfkeyv2_get(struct tdb *sa, void **headers, void **buffer) if (sa->tdb_udpencap_port) i+= sizeof(struct sadb_x_udpencap); + if (lenp) + *lenp = i; + + if (buffer == NULL) { + rval = 0; + goto ret; + } + if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) { rval = ENOMEM; goto ret; @@ -674,7 +682,7 @@ pfkeyv2_dump_walker(struct tdb *sa, void *state, int last) headers[0] = (void *) dump_state->sadb_msg; /* Get the information from the TDB to a PFKEYv2 message */ - if ((rval = pfkeyv2_get(sa, headers, &buffer)) != 0) + if ((rval = pfkeyv2_get(sa, headers, &buffer, NULL)) != 0) return (rval); if (last) @@ -1229,7 +1237,7 @@ pfkeyv2_send(struct socket *socket, void *message, int len) goto splxret; } - rval = pfkeyv2_get(sa2, headers, &freeme); + rval = pfkeyv2_get(sa2, headers, &freeme, NULL); if (rval) mode = PFKEYV2_SENDMESSAGE_UNICAST; @@ -2131,6 +2139,100 @@ pfkeyv2_expire(struct tdb *sa, u_int16_t type) return (rval); } +struct pfkeyv2_sysctl_walk { + void *w_where; + size_t w_len; + int w_op; + u_int8_t w_satype; +}; + +int +pfkeyv2_sysctl_walker(struct tdb *sa, void *arg, int last) +{ + struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg; + void *buffer = NULL; + int error = 0; + int buflen, i; + + if (w->w_satype != SADB_SATYPE_UNSPEC && + w->w_satype != sa->tdb_satype) + return (0); + + if (w->w_where) { + void *headers[SADB_EXT_MAX+1]; + struct sadb_msg msg; + + bzero(headers, sizeof(headers)); + if ((error = pfkeyv2_get(sa, headers, &buffer, &buflen)) != 0) + goto done; + if (w->w_len < sizeof(msg) + buflen) { + error = ENOMEM; + goto done; + } + /* prepend header */ + msg.sadb_msg_version = PF_KEY_V2; + msg.sadb_msg_pid = 0; + msg.sadb_msg_seq = 0; + msg.sadb_msg_satype = sa->tdb_satype; + msg.sadb_msg_type = SADB_DUMP; + msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t); + if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0) + goto done; + w->w_where += sizeof(msg); + w->w_len -= sizeof(msg); + /* set extension type */ + for (i = 1; i <= SADB_EXT_MAX; i++) + if (headers[i]) + ((struct sadb_ext *) + headers[i])->sadb_ext_type = i; + if ((error = copyout(buffer, w->w_where, buflen)) != 0) + goto done; + w->w_where += buflen; + w->w_len -= buflen; + } else { + if ((error = pfkeyv2_get(sa, NULL, NULL, &buflen)) != 0) + return (error); + w->w_len += buflen; + w->w_len += sizeof(struct sadb_msg); + } + +done: + if (buffer) + free(buffer, M_PFKEY); + return (error); +} + +int +pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, + void *new, size_t newlen) +{ + struct pfkeyv2_sysctl_walk w; + int s, error = EINVAL; + + if (new) + return (EPERM); + if (namelen < 1) + return (EINVAL); + w.w_op = name[0]; + w.w_satype = name[1]; + w.w_where = oldp; + w.w_len = oldp ? *oldlenp : 0; + + switch(w.w_op) { + case NET_KEY_SADB_DUMP: + if ((error = suser(curproc, 0)) != 0) + return (error); + s = spltdb(); + error = tdb_walk(pfkeyv2_sysctl_walker, &w); + splx(s); + if (oldp) + *oldlenp = w.w_where - oldp; + else + *oldlenp = w.w_len; + } + return (error); +} + int pfkeyv2_init(void) { @@ -2141,6 +2243,7 @@ pfkeyv2_init(void) pfkeyv2_version.create = &pfkeyv2_create; pfkeyv2_version.release = &pfkeyv2_release; pfkeyv2_version.send = &pfkeyv2_send; + pfkeyv2_version.sysctl = &pfkeyv2_sysctl; rval = pfkey_register(&pfkeyv2_version); return (rval); |