1 #include <minix/drivers.h> 2 #include <minix/ioctl.h> 3 #include <sys/ioc_fbd.h> 4 5 #include "action.h" 6 #include "rule.h" 7 8 static struct fbd_rule rules[MAX_RULES]; 9 static struct fbd_rule *matches[MAX_RULES]; 10 static int nr_matches; 11 12 /*===========================================================================* 13 * rule_ctl * 14 *===========================================================================*/ 15 int rule_ctl(unsigned long request, endpoint_t endpt, cp_grant_id_t grant) 16 { 17 /* Handle an I/O control request regarding rules. */ 18 fbd_rulenum_t i; 19 int r; 20 21 /* Note that any of the safecopy calls may fail if the ioctl is 22 * improperly defined in userland; never panic if they fail! 23 */ 24 switch (request) { 25 case FBDCADDRULE: 26 /* Find a free rule slot. */ 27 for (i = 1; i <= MAX_RULES; i++) 28 if (rules[i-1].num == 0) 29 break; 30 31 if (i == MAX_RULES+1) 32 return ENOMEM; 33 34 /* Copy in the rule. */ 35 if ((r = sys_safecopyfrom(endpt, grant, 0, 36 (vir_bytes) &rules[i-1], sizeof(rules[0]))) != OK) 37 return r; 38 39 /* Mark the rule as active, and return its number. */ 40 rules[i-1].num = i; 41 42 return i; 43 44 case FBDCDELRULE: 45 /* Copy in the given rule number. */ 46 if ((r = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &i, 47 sizeof(i))) != OK) 48 return r; 49 50 /* Fail if the given rule number is not valid or in use. 51 * Allow the caller to determine the maximum rule number. 52 */ 53 if (i <= 0 || i > MAX_RULES) return EINVAL; 54 55 if (rules[i-1].num != i) return ENOENT; 56 57 /* Mark the rule as not active. */ 58 rules[i-1].num = 0; 59 60 return OK; 61 62 case FBDCGETRULE: 63 /* Copy in just the rule number from the given structure. */ 64 if ((r = sys_safecopyfrom(endpt, grant, 65 offsetof(struct fbd_rule, num), (vir_bytes) &i, 66 sizeof(i))) != OK) 67 return r; 68 69 /* Fail if the given rule number is not valid or in use. 70 * Allow the caller to determine the maximum rule number. 71 */ 72 if (i <= 0 || i > MAX_RULES) return EINVAL; 73 74 if (rules[i-1].num != i) return ENOENT; 75 76 /* Copy out the entire rule as is. */ 77 return sys_safecopyto(endpt, grant, 0, (vir_bytes) &rules[i-1], 78 sizeof(rules[0])); 79 80 default: 81 return EINVAL; 82 } 83 } 84 85 /*===========================================================================* 86 * rule_match * 87 *===========================================================================*/ 88 static int rule_match(struct fbd_rule *rule, u64_t pos, size_t size, int flag) 89 { 90 /* Check whether the given rule matches the given parameters. As side 91 * effect, update counters in the rule as appropriate. 92 */ 93 94 /* Ranges must overlap (start < pos+size && end > pos). */ 95 if (rule->start >= pos + size || 96 (rule->end != 0 && rule->end <= pos)) 97 return FALSE; 98 99 /* Flags must match. */ 100 if (!(rule->flags & flag)) return FALSE; 101 102 /* This is a match, but is it supposed to trigger yet? */ 103 if (rule->skip > 0) { 104 rule->skip--; 105 106 return FALSE; 107 } 108 109 return TRUE; 110 } 111 112 /*===========================================================================* 113 * rule_find * 114 *===========================================================================*/ 115 int rule_find(u64_t pos, size_t size, int flag) 116 { 117 /* Find all matching rules, and return a hook mask. */ 118 struct fbd_rule *rule; 119 int i, hooks; 120 121 nr_matches = 0; 122 hooks = 0; 123 124 for (i = 0; i < MAX_RULES; i++) { 125 rule = &rules[i]; 126 127 if (rule->num == 0) continue; 128 129 if (!rule_match(rule, pos, size, flag)) 130 continue; 131 132 matches[nr_matches++] = rule; 133 134 /* If the rule has a limited lifetime, update it now. */ 135 if (rule->count > 0) { 136 rule->count--; 137 138 /* Disable the rule from future matching. */ 139 if (rule->count == 0) 140 rule->num = 0; 141 } 142 143 hooks |= action_mask(rule); 144 } 145 146 return hooks; 147 } 148 149 /*===========================================================================* 150 * rule_pre_hook * 151 *===========================================================================*/ 152 void rule_pre_hook(iovec_t *iov, unsigned *count, size_t *size, 153 u64_t *pos) 154 { 155 int i; 156 157 for (i = 0; i < nr_matches; i++) 158 if (action_mask(matches[i]) & PRE_HOOK) 159 action_pre_hook(matches[i], iov, count, size, pos); 160 } 161 162 /*===========================================================================* 163 * rule_io_hook * 164 *===========================================================================*/ 165 void rule_io_hook(char *buf, size_t size, u64_t pos, int flag) 166 { 167 int i; 168 169 for (i = 0; i < nr_matches; i++) 170 if (action_mask(matches[i]) & IO_HOOK) 171 action_io_hook(matches[i], buf, size, pos, flag); 172 } 173 174 /*===========================================================================* 175 * rule_post_hook * 176 *===========================================================================*/ 177 void rule_post_hook(size_t osize, int *result) 178 { 179 int i; 180 181 for (i = 0; i < nr_matches; i++) 182 if (action_mask(matches[i]) & POST_HOOK) 183 action_post_hook(matches[i], osize, result); 184 } 185