| 1179 | } |
| 1180 | |
| 1181 | static struct in6_addrpolicy * |
| 1182 | match_addrsel_policy(struct sockaddr_in6 *key) |
| 1183 | { |
| 1184 | struct addrsel_policyent *pent; |
| 1185 | struct in6_addrpolicy *bestpol = NULL, *pol; |
| 1186 | int matchlen, bestmatchlen = -1; |
| 1187 | u_char *mp, *ep, *k, *p, m; |
| 1188 | |
| 1189 | TAILQ_FOREACH(pent, &V_addrsel_policytab, ape_entry) { |
| 1190 | matchlen = 0; |
| 1191 | |
| 1192 | pol = &pent->ape_policy; |
| 1193 | mp = (u_char *)&pol->addrmask.sin6_addr; |
| 1194 | ep = mp + 16; /* XXX: scope field? */ |
| 1195 | k = (u_char *)&key->sin6_addr; |
| 1196 | p = (u_char *)&pol->addr.sin6_addr; |
| 1197 | for (; mp < ep && *mp; mp++, k++, p++) { |
| 1198 | m = *mp; |
| 1199 | if ((*k & m) != *p) |
| 1200 | goto next; /* not match */ |
| 1201 | if (m == 0xff) /* short cut for a typical case */ |
| 1202 | matchlen += 8; |
| 1203 | else { |
| 1204 | while (m >= 0x80) { |
| 1205 | matchlen++; |
| 1206 | m <<= 1; |
| 1207 | } |
| 1208 | } |
| 1209 | } |
| 1210 | |
| 1211 | /* matched. check if this is better than the current best. */ |
| 1212 | if (bestpol == NULL || |
| 1213 | matchlen > bestmatchlen) { |
| 1214 | bestpol = pol; |
| 1215 | bestmatchlen = matchlen; |
| 1216 | } |
| 1217 | |
| 1218 | next: |
| 1219 | continue; |
| 1220 | } |
| 1221 | |
| 1222 | return (bestpol); |
| 1223 | } |
no outgoing calls
no test coverage detected