| 233 | } |
| 234 | |
| 235 | static struct encaptab * |
| 236 | encap_attach(struct encaptab_head *head, const struct encap_config *cfg, |
| 237 | void *arg, int mflags) |
| 238 | { |
| 239 | struct encaptab *ep, *tmp; |
| 240 | |
| 241 | if (cfg == NULL || cfg->input == NULL || |
| 242 | (cfg->check == NULL && cfg->lookup == NULL) || |
| 243 | (cfg->lookup != NULL && cfg->exact_match != ENCAP_DRV_LOOKUP) || |
| 244 | (cfg->exact_match == ENCAP_DRV_LOOKUP && cfg->lookup == NULL)) |
| 245 | return (NULL); |
| 246 | |
| 247 | ep = malloc(sizeof(*ep), M_NETADDR, mflags); |
| 248 | if (ep == NULL) |
| 249 | return (NULL); |
| 250 | |
| 251 | ep->proto = cfg->proto; |
| 252 | ep->min_length = cfg->min_length; |
| 253 | ep->exact_match = cfg->exact_match; |
| 254 | ep->arg = arg; |
| 255 | ep->lookup = cfg->exact_match == ENCAP_DRV_LOOKUP ? cfg->lookup: NULL; |
| 256 | ep->check = cfg->exact_match != ENCAP_DRV_LOOKUP ? cfg->check: NULL; |
| 257 | ep->input = cfg->input; |
| 258 | |
| 259 | ENCAP_WLOCK(); |
| 260 | CK_LIST_FOREACH(tmp, head, chain) { |
| 261 | if (tmp->exact_match <= ep->exact_match) |
| 262 | break; |
| 263 | } |
| 264 | if (tmp == NULL) |
| 265 | CK_LIST_INSERT_HEAD(head, ep, chain); |
| 266 | else |
| 267 | CK_LIST_INSERT_BEFORE(tmp, ep, chain); |
| 268 | ENCAP_WUNLOCK(); |
| 269 | return (ep); |
| 270 | } |
| 271 | |
| 272 | static int |
| 273 | encap_detach(struct encaptab_head *head, const struct encaptab *cookie) |
no test coverage detected