aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/cipso_ipv4.c
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2006-11-17 17:38:49 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:24:10 -0500
commit91b1ed0afdbffbda88c472ef72af37e19b7876fb (patch)
tree29a1b289edec3e83408d021c2e26836727bef93e /net/ipv4/cipso_ipv4.c
parent6ce61a7c2678800cfe59a5f4a41ce8f785b9d355 (diff)
NetLabel: fixup the handling of CIPSOv4 tags to allow for multiple tag types
While the original CIPSOv4 code had provisions for multiple tag types the implementation was not as great as it could be, pushing a lot of non-tag specific processing into the tag specific code blocks. This patch fixes that issue making it easier to support multiple tag types in the future. Signed-off-by: Paul Moore <paul.moore@hp.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'net/ipv4/cipso_ipv4.c')
-rw-r--r--net/ipv4/cipso_ipv4.c113
1 files changed, 53 insertions, 60 deletions
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 23a968f754be..a056278ad626 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -958,35 +958,28 @@ static int cipso_v4_map_cat_rbm_ntoh(const struct cipso_v4_doi *doi_def,
958 * Protocol Handling Functions 958 * Protocol Handling Functions
959 */ 959 */
960 960
961#define CIPSO_V4_OPT_LEN_MAX 40
961#define CIPSO_V4_HDR_LEN 6 962#define CIPSO_V4_HDR_LEN 6
962 963
963/** 964/**
964 * cipso_v4_gentag_hdr - Generate a CIPSO option header 965 * cipso_v4_gentag_hdr - Generate a CIPSO option header
965 * @doi_def: the DOI definition 966 * @doi_def: the DOI definition
966 * @len: the total tag length in bytes 967 * @len: the total tag length in bytes, not including this header
967 * @buf: the CIPSO option buffer 968 * @buf: the CIPSO option buffer
968 * 969 *
969 * Description: 970 * Description:
970 * Write a CIPSO header into the beginning of @buffer. Return zero on success, 971 * Write a CIPSO header into the beginning of @buffer.
971 * negative values on failure.
972 * 972 *
973 */ 973 */
974static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def, 974static void cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
975 u32 len, 975 unsigned char *buf,
976 unsigned char *buf) 976 u32 len)
977{ 977{
978 if (CIPSO_V4_HDR_LEN + len > 40)
979 return -ENOSPC;
980
981 buf[0] = IPOPT_CIPSO; 978 buf[0] = IPOPT_CIPSO;
982 buf[1] = CIPSO_V4_HDR_LEN + len; 979 buf[1] = CIPSO_V4_HDR_LEN + len;
983 *(__be32 *)&buf[2] = htonl(doi_def->doi); 980 *(__be32 *)&buf[2] = htonl(doi_def->doi);
984
985 return 0;
986} 981}
987 982
988#define CIPSO_V4_TAG1_CAT_LEN 30
989
990/** 983/**
991 * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1) 984 * cipso_v4_gentag_rbm - Generate a CIPSO restricted bitmap tag (type #1)
992 * @doi_def: the DOI definition 985 * @doi_def: the DOI definition
@@ -997,71 +990,50 @@ static int cipso_v4_gentag_hdr(const struct cipso_v4_doi *doi_def,
997 * Description: 990 * Description:
998 * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The 991 * Generate a CIPSO option using the restricted bitmap tag, tag type #1. The
999 * actual buffer length may be larger than the indicated size due to 992 * actual buffer length may be larger than the indicated size due to
1000 * translation between host and network category bitmaps. Returns zero on 993 * translation between host and network category bitmaps. Returns the size of
1001 * success, negative values on failure. 994 * the tag on success, negative values on failure.
1002 * 995 *
1003 */ 996 */
1004static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, 997static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def,
1005 const struct netlbl_lsm_secattr *secattr, 998 const struct netlbl_lsm_secattr *secattr,
1006 unsigned char **buffer, 999 unsigned char *buffer,
1007 u32 *buffer_len) 1000 u32 buffer_len)
1008{ 1001{
1009 int ret_val; 1002 int ret_val;
1010 unsigned char *buf = NULL; 1003 u32 tag_len;
1011 u32 buf_len;
1012 u32 level; 1004 u32 level;
1013 1005
1014 if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0) 1006 if ((secattr->flags & NETLBL_SECATTR_MLS_LVL) == 0)
1015 return -EPERM; 1007 return -EPERM;
1016 1008
1017 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) { 1009 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1018 buf = kzalloc(CIPSO_V4_HDR_LEN + 4 + CIPSO_V4_TAG1_CAT_LEN, 1010 if (ret_val != 0)
1019 GFP_ATOMIC); 1011 return ret_val;
1020 if (buf == NULL)
1021 return -ENOMEM;
1022 1012
1013 if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
1023 ret_val = cipso_v4_map_cat_rbm_hton(doi_def, 1014 ret_val = cipso_v4_map_cat_rbm_hton(doi_def,
1024 secattr->mls_cat, 1015 secattr->mls_cat,
1025 secattr->mls_cat_len, 1016 secattr->mls_cat_len,
1026 &buf[CIPSO_V4_HDR_LEN + 4], 1017 &buffer[4],
1027 CIPSO_V4_TAG1_CAT_LEN); 1018 buffer_len - 4);
1028 if (ret_val < 0) 1019 if (ret_val < 0)
1029 goto gentag_failure; 1020 return ret_val;
1030 1021
1031 /* This will send packets using the "optimized" format when 1022 /* This will send packets using the "optimized" format when
1032 * possibile as specified in section 3.4.2.6 of the 1023 * possibile as specified in section 3.4.2.6 of the
1033 * CIPSO draft. */ 1024 * CIPSO draft. */
1034 if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) 1025 if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10)
1035 buf_len = 14; 1026 tag_len = 14;
1036 else 1027 else
1037 buf_len = 4 + ret_val; 1028 tag_len = 4 + ret_val;
1038 } else { 1029 } else
1039 buf = kzalloc(CIPSO_V4_HDR_LEN + 4, GFP_ATOMIC); 1030 tag_len = 4;
1040 if (buf == NULL)
1041 return -ENOMEM;
1042 buf_len = 4;
1043 }
1044
1045 ret_val = cipso_v4_map_lvl_hton(doi_def, secattr->mls_lvl, &level);
1046 if (ret_val != 0)
1047 goto gentag_failure;
1048
1049 ret_val = cipso_v4_gentag_hdr(doi_def, buf_len, buf);
1050 if (ret_val != 0)
1051 goto gentag_failure;
1052
1053 buf[CIPSO_V4_HDR_LEN] = 0x01;
1054 buf[CIPSO_V4_HDR_LEN + 1] = buf_len;
1055 buf[CIPSO_V4_HDR_LEN + 3] = level;
1056 1031
1057 *buffer = buf; 1032 buffer[0] = 0x01;
1058 *buffer_len = CIPSO_V4_HDR_LEN + buf_len; 1033 buffer[1] = tag_len;
1034 buffer[3] = level;
1059 1035
1060 return 0; 1036 return tag_len;
1061
1062gentag_failure:
1063 kfree(buf);
1064 return ret_val;
1065} 1037}
1066 1038
1067/** 1039/**
@@ -1284,7 +1256,7 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1284{ 1256{
1285 int ret_val = -EPERM; 1257 int ret_val = -EPERM;
1286 u32 iter; 1258 u32 iter;
1287 unsigned char *buf = NULL; 1259 unsigned char *buf;
1288 u32 buf_len = 0; 1260 u32 buf_len = 0;
1289 u32 opt_len; 1261 u32 opt_len;
1290 struct ip_options *opt = NULL; 1262 struct ip_options *opt = NULL;
@@ -1300,17 +1272,28 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1300 if (sk == NULL) 1272 if (sk == NULL)
1301 return 0; 1273 return 0;
1302 1274
1275 /* We allocate the maximum CIPSO option size here so we are probably
1276 * being a little wasteful, but it makes our life _much_ easier later
1277 * on and after all we are only talking about 40 bytes. */
1278 buf_len = CIPSO_V4_OPT_LEN_MAX;
1279 buf = kmalloc(buf_len, GFP_ATOMIC);
1280 if (buf == NULL) {
1281 ret_val = -ENOMEM;
1282 goto socket_setattr_failure;
1283 }
1284
1303 /* XXX - This code assumes only one tag per CIPSO option which isn't 1285 /* XXX - This code assumes only one tag per CIPSO option which isn't
1304 * really a good assumption to make but since we only support the MAC 1286 * really a good assumption to make but since we only support the MAC
1305 * tags right now it is a safe assumption. */ 1287 * tags right now it is a safe assumption. */
1306 iter = 0; 1288 iter = 0;
1307 do { 1289 do {
1290 memset(buf, 0, buf_len);
1308 switch (doi_def->tags[iter]) { 1291 switch (doi_def->tags[iter]) {
1309 case CIPSO_V4_TAG_RBITMAP: 1292 case CIPSO_V4_TAG_RBITMAP:
1310 ret_val = cipso_v4_gentag_rbm(doi_def, 1293 ret_val = cipso_v4_gentag_rbm(doi_def,
1311 secattr, 1294 secattr,
1312 &buf, 1295 &buf[CIPSO_V4_HDR_LEN],
1313 &buf_len); 1296 buf_len - CIPSO_V4_HDR_LEN);
1314 break; 1297 break;
1315 default: 1298 default:
1316 ret_val = -EPERM; 1299 ret_val = -EPERM;
@@ -1318,11 +1301,13 @@ int cipso_v4_socket_setattr(const struct socket *sock,
1318 } 1301 }
1319 1302
1320 iter++; 1303 iter++;
1321 } while (ret_val != 0 && 1304 } while (ret_val < 0 &&
1322 iter < CIPSO_V4_TAG_MAXCNT && 1305 iter < CIPSO_V4_TAG_MAXCNT &&
1323 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID); 1306 doi_def->tags[iter] != CIPSO_V4_TAG_INVALID);
1324 if (ret_val != 0) 1307 if (ret_val < 0)
1325 goto socket_setattr_failure; 1308 goto socket_setattr_failure;
1309 cipso_v4_gentag_hdr(doi_def, buf, ret_val);
1310 buf_len = CIPSO_V4_HDR_LEN + ret_val;
1326 1311
1327 /* We can't use ip_options_get() directly because it makes a call to 1312 /* We can't use ip_options_get() directly because it makes a call to
1328 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and 1313 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
@@ -1396,6 +1381,10 @@ int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr)
1396 rcu_read_unlock(); 1381 rcu_read_unlock();
1397 return -ENOMSG; 1382 return -ENOMSG;
1398 } 1383 }
1384
1385 /* XXX - This code assumes only one tag per CIPSO option which isn't
1386 * really a good assumption to make but since we only support the MAC
1387 * tags right now it is a safe assumption. */
1399 switch (cipso_ptr[6]) { 1388 switch (cipso_ptr[6]) {
1400 case CIPSO_V4_TAG_RBITMAP: 1389 case CIPSO_V4_TAG_RBITMAP:
1401 ret_val = cipso_v4_parsetag_rbm(doi_def, 1390 ret_val = cipso_v4_parsetag_rbm(doi_def,
@@ -1458,6 +1447,10 @@ int cipso_v4_skbuff_getattr(const struct sk_buff *skb,
1458 doi_def = cipso_v4_doi_getdef(doi); 1447 doi_def = cipso_v4_doi_getdef(doi);
1459 if (doi_def == NULL) 1448 if (doi_def == NULL)
1460 goto skbuff_getattr_return; 1449 goto skbuff_getattr_return;
1450
1451 /* XXX - This code assumes only one tag per CIPSO option which isn't
1452 * really a good assumption to make but since we only support the MAC
1453 * tags right now it is a safe assumption. */
1461 switch (cipso_ptr[6]) { 1454 switch (cipso_ptr[6]) {
1462 case CIPSO_V4_TAG_RBITMAP: 1455 case CIPSO_V4_TAG_RBITMAP:
1463 ret_val = cipso_v4_parsetag_rbm(doi_def, 1456 ret_val = cipso_v4_parsetag_rbm(doi_def,