1 /* 2 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the project nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 #include <sys/types.h> 33 #include <sys/param.h> 34 #include <sys/socket.h> 35 36 #include <netkey/key_var.h> 37 #include <netinet/in.h> 38 #include <netinet6/ipsec.h> 39 40 #include <arpa/inet.h> 41 42 #include <stdlib.h> 43 #include <string.h> 44 #include <netdb.h> 45 46 #include "ipsec_strerror.h" 47 48 static const char *ipsp_dir_strs[] = { 49 "any", "in", "out", 50 }; 51 52 static const char *ipsp_policy_strs[] = { 53 "discard", "none", "ipsec", "entrust", "bypass", 54 }; 55 56 static int set_addresses __P((char *buf, caddr_t ptr)); 57 58 /* 59 * policy is sadb_x_policy buffer. 60 * Must call free() later. 61 * When delimiter == NULL, alternatively ' '(space) is applied. 62 */ 63 char * 64 ipsec_dump_policy(policy, delimiter) 65 caddr_t policy; 66 char *delimiter; 67 { 68 struct sadb_x_policy *xpl = (struct sadb_x_policy *)policy; 69 struct sadb_x_ipsecrequest *xisr; 70 int xtlen, buflen; 71 char *buf; 72 int error; 73 74 /* sanity check */ 75 if (policy == NULL) 76 return NULL; 77 if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) { 78 ipsec_errcode = EIPSEC_INVAL_EXTTYPE; 79 return NULL; 80 } 81 82 /* set delimiter */ 83 if (delimiter == NULL) 84 delimiter = " "; 85 86 switch (xpl->sadb_x_policy_dir) { 87 case IPSEC_DIR_ANY: 88 case IPSEC_DIR_INBOUND: 89 case IPSEC_DIR_OUTBOUND: 90 break; 91 default: 92 ipsec_errcode = EIPSEC_INVAL_DIR; 93 return NULL; 94 } 95 96 switch (xpl->sadb_x_policy_type) { 97 case IPSEC_POLICY_DISCARD: 98 case IPSEC_POLICY_NONE: 99 case IPSEC_POLICY_IPSEC: 100 case IPSEC_POLICY_BYPASS: 101 case IPSEC_POLICY_ENTRUST: 102 break; 103 default: 104 ipsec_errcode = EIPSEC_INVAL_POLICY; 105 return NULL; 106 } 107 108 buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir]) 109 + 1 /* space */ 110 + strlen(ipsp_policy_strs[xpl->sadb_x_policy_type]) 111 + 1; /* NUL */ 112 113 if ((buf = malloc(buflen)) == NULL) { 114 ipsec_errcode = EIPSEC_NO_BUFS; 115 return NULL; 116 } 117 strcpy(buf, ipsp_dir_strs[xpl->sadb_x_policy_dir]); 118 strcat(buf, " "); 119 strcat(buf, ipsp_policy_strs[xpl->sadb_x_policy_type]); 120 121 if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) { 122 ipsec_errcode = EIPSEC_NO_ERROR; 123 return buf; 124 } 125 126 xtlen = PFKEY_EXTLEN(xpl) - sizeof(*xpl); 127 xisr = (struct sadb_x_ipsecrequest *)(xpl + 1); 128 129 /* count length of buffer for use */ 130 /* XXX non-seriously */ 131 while (xtlen > 0) { 132 buflen += 20; 133 if (xisr->sadb_x_ipsecrequest_mode ==IPSEC_MODE_TUNNEL) 134 buflen += 50; 135 xtlen -= xisr->sadb_x_ipsecrequest_len; 136 xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr 137 + xisr->sadb_x_ipsecrequest_len); 138 } 139 140 /* validity check */ 141 if (xtlen < 0) { 142 ipsec_errcode = EIPSEC_INVAL_SADBMSG; 143 free(buf); 144 return NULL; 145 } 146 147 if ((buf = realloc(buf, buflen)) == NULL) { 148 ipsec_errcode = EIPSEC_NO_BUFS; 149 return NULL; 150 } 151 152 xtlen = PFKEY_EXTLEN(xpl) - sizeof(*xpl); 153 xisr = (struct sadb_x_ipsecrequest *)(xpl + 1); 154 155 while (xtlen > 0) { 156 strcat(buf, delimiter); 157 158 switch (xisr->sadb_x_ipsecrequest_proto) { 159 case IPPROTO_ESP: 160 strcat(buf, "esp"); 161 break; 162 case IPPROTO_AH: 163 strcat(buf, "ah"); 164 break; 165 case IPPROTO_IPCOMP: 166 strcat(buf, "ipcomp"); 167 break; 168 default: 169 ipsec_errcode = EIPSEC_INVAL_PROTO; 170 free(buf); 171 return NULL; 172 } 173 174 strcat(buf, "/"); 175 176 switch (xisr->sadb_x_ipsecrequest_mode) { 177 case IPSEC_MODE_ANY: 178 strcat(buf, "any"); 179 break; 180 case IPSEC_MODE_TRANSPORT: 181 strcat(buf, "transport"); 182 break; 183 case IPSEC_MODE_TUNNEL: 184 strcat(buf, "tunnel"); 185 break; 186 default: 187 ipsec_errcode = EIPSEC_INVAL_MODE; 188 free(buf); 189 return NULL; 190 } 191 192 strcat(buf, "/"); 193 194 if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) { 195 error = set_addresses(buf, (caddr_t)(xisr + 1)); 196 if (error) { 197 ipsec_errcode = EIPSEC_INVAL_MODE; 198 free(buf); 199 return NULL; 200 } 201 } 202 203 switch (xisr->sadb_x_ipsecrequest_level) { 204 case IPSEC_LEVEL_DEFAULT: 205 strcat(buf, "/default"); 206 break; 207 case IPSEC_LEVEL_USE: 208 strcat(buf, "/use"); 209 break; 210 case IPSEC_LEVEL_REQUIRE: 211 strcat(buf, "/require"); 212 break; 213 case IPSEC_LEVEL_UNIQUE: 214 strcat(buf, "/unique"); 215 break; 216 default: 217 ipsec_errcode = EIPSEC_INVAL_LEVEL; 218 free(buf); 219 return NULL; 220 } 221 222 xtlen -= xisr->sadb_x_ipsecrequest_len; 223 xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr 224 + xisr->sadb_x_ipsecrequest_len); 225 } 226 227 ipsec_errcode = EIPSEC_NO_ERROR; 228 return buf; 229 } 230 231 static int 232 set_addresses(buf, ptr) 233 char *buf; 234 caddr_t ptr; 235 { 236 char tmp[100]; /* XXX */ 237 struct sockaddr *saddr = (struct sockaddr *)ptr; 238 239 getnameinfo(saddr, saddr->sa_len, tmp, sizeof(tmp), 240 NULL, 0, NI_NUMERICHOST); 241 242 strcat(buf, tmp); 243 244 strcat(buf, "-"); 245 246 saddr = (struct sockaddr *)((caddr_t)saddr + saddr->sa_len); 247 getnameinfo(saddr, saddr->sa_len, tmp, sizeof(tmp), 248 NULL, 0, NI_NUMERICHOST); 249 250 strcat(buf, tmp); 251 252 return 0; 253 } 254